WPF: изменение CollectionView из диспетчера по-прежнему вызывает ошибки


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

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 из потока, отличного от потока диспетчера.

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

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

1 ответ:

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

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

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

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

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

    Dispatcher OwningDispatcher { get; private set; }
}

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