WPF:从Dispatcher修改CollectionView仍然会抛出错误

Dus*_*sda 4 c# wpf dispatcher

我有以下一些代码,可以在用户离开时修改可观察的"屏幕"集合.

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);
    }
Run Code Online (Sandbox Code Playgroud)

这包含在客户端Dispatcher的调用中,据说可以解决与CollectionViews相关的线程问题.但是,我仍然得到以下异常:

这种类型的CollectionView不支持从与Dispatcher线程不同的线程更改其SourceCollection.

您在上面看到的Dispatcher是在WPF应用程序的MainViewModel中设置的(我们使用的是MVVM),如下所示:

public Dispatcher ClientDispatcher
{
    get { return Dispatcher.CurrentDispatcher; }
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*Jon 6

来自以下文件CurrentDispatcher:

获取当前正在执行的线程的Dispatcher,并创建一个新的Dispatcher(如果尚未与该线程关联).

看起来你正在访问CurrentDispatcher 而不在你的UI线程中,并在它上面调用你的操作(即,Invoke完全没有效果,因为你所在的线程没有Dispatcher;一个新的就在现场创建,电话转到它).

您应该Dispatcher.CurrentDispatcher在创建Client实例的位置保存值(假设您是在UI线程中执行此操作),例如:

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

    Dispatcher OwningDispatcher { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)

如果您的Client实例未在UI线程上创建,则需要某种方法来获取正确的值Dispatcher.