WPF:从 Dispatcher 修改 CollectionView 仍然会引发错误

发布于 2024-09-01 11:14:50 字数 899 浏览 4 评论 0原文

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

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。

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

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

I have the following bit of code that modifies an observable collection of 'screens' whenever a user leaves.

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

This is wrapped in a call to the client's Dispatcher, supposedly to get past the threading issues related to CollectionViews. However, I still get the following exception:

This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread.

The Dispatcher you see above is set in the WPF application's MainViewModel (we're using MVVM), like so:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

心凉 2024-09-08 11:14:50

来自 CurrentDispatcher

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

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

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

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

    Dispatcher OwningDispatcher { get; private set; }
}

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

From the documentation of CurrentDispatcher:

Gets the Dispatcher for the thread currently executing and creates a new Dispatcher if one is not already associated with the thread.

It looks like you are accessing CurrentDispatcher while not in your UI thread, and invoking your operation on it (i.e., the Invoke has no effect at all because the thread you are in does not have a Dispatcher; a new one is created on the spot and the call goes to it).

You should be saving the value of Dispatcher.CurrentDispatcher at the point where you create the Client instances (assuming you are doing that from within the UI thread), for example:

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

    Dispatcher OwningDispatcher { get; private set; }
}

If your Client instances are not created on the UI thread, you need some way of getting the correct value of Dispatcher over to them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文