WPF: модификация CollectionView из Dispatcher по-прежнему выдает ошибки - PullRequest
4 голосов
/ 14 мая 2010

У меня есть следующий фрагмент кода, который изменяет наблюдаемую коллекцию «экранов» всякий раз, когда пользователь уходит.

void OnUserLeft(int roomId, int userId, string username)
    {
        client.ClientDispatcher.Invoke(
            (Action<int>)((id) => 
            {
                Console.WriteLine("Hello before the storm!");
                var screensToCheck = client.Screens.Where(s => s.CpuId == id).ToList();
                screensToCheck.Each(s => client.Screens.Remove(s));
                Console.WriteLine("Hello there!");
            }), userId);
    }

Это обернуто в вызов клиентского диспетчера, предположительно, чтобы обойти проблемы потоков, связанные с CollectionViews. Тем не менее, я все еще получаю следующее исключение:

Этот тип CollectionView не поддерживает изменения в его SourceCollection из потока, отличного от потока Dispatcher.

Диспетчер, который вы видите выше, установлен в MainViewModel приложения WPF (мы используем MVVM), например так:

public Dispatcher ClientDispatcher
{
    get { return Dispatcher.CurrentDispatcher; }
}

1 Ответ

6 голосов
/ 14 мая 2010

Из документации CurrentDispatcher:

Получает диспетчер для потока, выполняемого в данный момент, и создает новый диспетчер, если он еще не связан с потоком.

Похоже, что вы обращаетесь к CurrentDispatcher , не входя в ваш поток пользовательского интерфейса , и вызываете вашу операцию над ним (т. Е. Invoke не имеет никакого эффекта вообще, потому что поток, в котором вы находитесь, не имеет Диспетчер; новый создается на месте, и вызов переходит к нему).

Вы должны сохранить значение Dispatcher.CurrentDispatcher в точке, где вы создаете Client экземпляры (при условии, что вы делаете это из потока пользовательского интерфейса), например:

class Client {
    Client() {
        this.OwningDispatcher = Dispatcher.CurrentDispatcher;
    }

    Dispatcher OwningDispatcher { get; private set; }
}

Если ваши Client экземпляры не созданы в потоке пользовательского интерфейса, вам нужно каким-то образом передать им правильное значение Dispatcher.

...