我有以下代码,每当用户离开时,它都会修改一个可观察的“屏幕”集合。

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不支持从与Dispatcher线程不同的线程更改其SourceCollection。
上面看到的调度器是在wpf应用程序的mainviewmodel中设置的(我们使用的是mvvm),如下所示:
public Dispatcher ClientDispatcher
{
    get { return Dispatcher.CurrentDispatcher; }
}

最佳答案

CurrentDispatcher的文档中:
获取当前正在执行的线程的调度程序,如果某个调度程序尚未与该线程关联,则创建新的调度程序。
看起来您正在访问CurrentDispatcher而不在ui线程中,并且正在调用对它的操作(即,调用根本没有任何效果,因为您所在的线程没有分派器;一个新的线程是在现场创建的,调用会转到它)。
您应该在创建Dispatcher.CurrentDispatcher实例时保存Client的值(假设您是在ui线程内执行此操作),例如:

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

    Dispatcher OwningDispatcher { get; private set; }
}

如果您的Client实例不是在ui线程上创建的,则需要某种方法将Dispatcher的正确值传递给它们。

09-25 13:55