gpt4 book ai didi

wpf - 如何处理跨线程访问异常?

转载 作者:行者123 更新时间:2023-12-02 02:41:52 24 4
gpt4 key购买 nike

在 WPF 中使用多线程时可能出现的常见异常是:

The calling thread cannot access this object because a different thread owns it

有哪些选项可以正确处理这个问题?

最佳答案

根据情况有多种选择:

从另一个线程访问控件

例如使用进度信息更新 TextBlock。

  • Data Binding :

    在这种情况下,您可以做的最简单的事情就是避免与控件直接交互。您只需 bind您想要访问或修改其类 implements 的对象的属性 INotifyPropertyChanged 然后在该对象上设置属性。框架将为您处理剩下的事情。 (一般来说,您很少需要直接与 UI 元素交互,您几乎总是可以绑定(bind)相应的属性并使用绑定(bind)源;可能需要直接控制访问的一种情况是控件创作。)

    在某些情况下,仅数据绑定(bind)是不够的,例如当尝试修改绑定(bind) ObservableCollection<T> 时,为此你需要...

  • Dispatching :

    您可以将访问代码分派(dispatch)到拥有该对象的线程,这可以通过调用 Invoke 来完成或 BeginInvoke Dispatcher 拥有正在访问的对象(可以在另一个线程上获取此 Dispatcher)。

    例如

    new Thread(ThisThreadStart).Start();
    void ThisThreadStart()
    {
    textBlock.Dispatcher.Invoke(new Action(() => textBlock.Text = "Test"));
    }

    如果不清楚某个方法在哪个线程上执行,您可以使用 Dispatcher.CheckAccess 直接分派(dispatch)或执行操作。

    例如

    void Update()
    {
    Action action = () => myTextBlock.Text = "Test";
    var dispatcher = myTextBlock.Dispatcher;
    if (dispatcher.CheckAccess())
    action();
    else
    dispatcher.Invoke(action);
    }

    如果对象不是 DispatcherObject 并且您仍然需要关联的 Dispatcher您可以使用 Dispatcher.CurrentDispatcher 在创建对象的线程中(因此在线程执行的方法中这样做不会有任何好处)。为了方便起见,您通常在应用程序的主 UI 线程上创建对象;你可以得到该线程的 Dispatcher从任何地方使用 Application.Current.Dispatcher .

特殊情况:

  • BackgroundWorker

    将任何控制访问权限移至 ProgressChanged 因为它发生在创建实例的线程上(当然应该是 UI 线程)

  • 计时器

    在 WPF 中,您可以使用 DispatcherTimer 为了方便起见,它会为您进行调度,因此 Tick 中的任何代码在关联的调度程序上调用。如果您可以将调度委托(delegate)给数据绑定(bind)系统,您当然也可以使用普通的计时器。

您可以阅读有关 Dispatcher 如何进行的更多信息队列工作和 WPF 线程一般 on MSDN .

访问在另一个线程上创建的对象

例如在后台加载图像。

如果有问题的对象不是 Freezable 一般来说,您应该避免在另一个线程上创建它或限制对创建线程的访问。如果是Freezable您只需调用 Freeze 使其可供其他线程访问。

从另一个线程访问数据对象

也就是说,正在更新实例的类型是用户代码。如果抛出异常,这种情况可能是由使用 DependencyObject 的人引起的。作为数据类的基类型。

这种情况与访问控件相同,可以应用相同的方法,但通常应该首先避免这种情况。当然,这允许通过 dependency properties 发送简单的属性更改通知。这些属性也可以绑定(bind),但通常不值得放弃线程独立性。您可以通过 INotifyPropertyChanged 获取变更通知WPF 中的绑定(bind)系统本质上是不对称的,总是有一个被绑定(bind)的属性(目标)以及作为此绑定(bind)的源的东西。通常,UI 是目标,数据是源,这意味着只有 UI 组件才需要依赖属性。

关于wpf - 如何处理跨线程访问异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11923865/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com