【问题标题】:WPF: Modifying CollectionView from Dispatcher still throws errorsWPF:从 Dispatcher 修改 CollectionView 仍然会引发错误
【发布时间】:2010-05-13 21:45:41
【问题描述】:

我有以下代码,可以在用户离开时修改可观察的“屏幕”集合。

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);
    }

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

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

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

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

【问题讨论】:

  • 究竟什么是“客户的调度员”?
  • 抱歉,在问题中添加了一些关于“ClientDispatcher”的信息。

标签: c# wpf dispatcher


【解决方案1】:

来自CurrentDispatcher的文档:

获取当前正在执行的线程的 Dispatcher,如果尚未与线程关联,则创建一个新的 Dispatcher。

看起来您正在访问CurrentDispatcher而不是在您的 UI 线程中,并在其上调用您的操作(即,Invoke 根本没有效果,因为您所在的线程没有有一个 Dispatcher;当场创建一个新的 Dispatcher,然后调用它)。

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

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

    Dispatcher OwningDispatcher { get; private set; }
}

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

【讨论】:

  • 这是我们第一次真正尝试删除某些内容,使用 Dispatcher 这样做。所以你是说我们的 Dispatcher 可能一开始就没有正确实现?我现在就试试。
  • 成功!先生,你太棒了。
  • 我不会把这称为才华横溢的结果。我只是仔细阅读了代码使用的功能的文档。 :-)
猜你喜欢
  • 1970-01-01
  • 2017-08-13
  • 2013-08-03
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
  • 2014-05-30
  • 2018-05-12
相关资源
最近更新 更多