【问题标题】:Understanding which object is owned by which thread [duplicate]了解哪个对象由哪个线程拥有[重复]
【发布时间】:2022-03-06 17:53:33
【问题描述】:

尝试从另一个线程访问 WPF 控件会导致 'System.InvalidOperationException'(跨线程访问冲突)。 异常的描述说,访问的对象不属于调用线程

以下代码显示,当第二个线程访问非 WPF-Control 对象时,不会引发 'System.InvalidOperationException'。但是为什么呢?

如何确定哪个对象由哪个线程拥有以避免此异常?

namespace Threading {
    
    public class TestObject {
        public Object Data { get; set; }
    }
    
    public partial class MainWindow : Window {
        TestObject _toOwnedByUI;     
        TextBox _txtOwnedByUI;
        BackgroundWorker _bw;

        public MainWindow () {
            InitializeComponent ();
            _bw = new BackgroundWorker ();
            _txtOwnedByUI = OutputBox;
            _bw.DoWork += onBwDoWork;
        }

        private void Button_Click (object sender, RoutedEventArgs e) {
            // initvalues from UI-Thread
            _toOwnedByUI = new TestObject () { Data = "UI Thread INIT" };
            _txtOwnedByUI.Text = "UI Thread INIT";
            // Start Second Thread
            _bw.RunWorkerAsync ();
        }

        // -------------------------------------------------------------------------         
        private void onBwDoWork(Object Sender, DoWorkEventArgs e) {
            // Change Values of testobjects by Second Thread
            _toOwnedByUI.Data = "Changed by BW-Thread";
            _txtOwnedByUI.Text = "Changed by BW-Thread";        // <----- throws System.InvalidOperationException : Invalid Thread
        }
    }
}

【问题讨论】:

  • 只有 UI 对象具有线程亲和性,您的 TestObject 类的对象可以从任何线程访问。

标签: c# wpf multithreading


【解决方案1】:

将对象与线程相关联是WPF 概念 - 它适用于所有对象。

每个WPF 对象都派生自DispatcherObject,它与当前线程的调度程序相关联。

稍后,通过调用VerifyAccess() 手动保护此对象上的所有操作免受跨线程调用,如果调用线程与“所有者”线程不同,则会引发异常。

https://referencesource.microsoft.com/#WindowsBase/Base/System/Windows/Threading/DispatcherObject.cs,85082c8bba6e8038

例如,您可以通过从DispatcherObject 派生并使用VerifyAccess() 保护Data 属性getter 和setter 来在TestObject 类中完成相同的行为。

最后,您假设 TestObject _tbOwnedByUI 由 UI 线程拥有是错误的,默认情况下对象没有这样的概念/行为。这几乎回答了问题。

【讨论】:

    猜你喜欢
    • 2013-06-16
    • 2020-11-13
    • 2020-12-07
    • 2017-11-25
    • 1970-01-01
    • 1970-01-01
    • 2018-12-24
    • 2011-02-13
    相关资源
    最近更新 更多