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 ответ:
Из документации
CurrentDispatcher
:Получает диспетчер для текущего выполняющегося потока и создает новый диспетчер, если он еще не связан с потоком.
Похоже, что вы получаете доступ
CurrentDispatcher
в то время как не в вашем потоке пользовательского интерфейса , и вызов вашей операции на нем (т. е. вызов не имеет никакого эффекта вообще, потому что поток, в котором вы находитесь, не имеет диспетчера; новый создается на месте, и вызов идет к он).Вы должны сохранять значение
Dispatcher.CurrentDispatcher
в точке, где вы создаете экземплярыClient
(предполагая, что вы делаете это из потока пользовательского интерфейса), например:class Client { Client() { this.OwningDispatcher = Dispatcher.CurrentDispatcher; } Dispatcher OwningDispatcher { get; private set; } }
Если ваши экземпляры
Client
не созданы в потоке пользовательского интерфейса, вам нужно каким-то образом передать им правильное значениеDispatcher
.