了解哪个对象由哪个线程拥有

Understanding which object is owned by which thread

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

以下代码显示当第二个线程访问非 WPF 控制对象时,不会抛出 '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
        }
    }
}

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

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

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

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

例如,您可以通过从 DispatcherObject 派生并保护 Data 属性 [=36] 在 TestObject class 中实现相同的行为=] 和 setter 与 VerifyAccess().

最后,你假设 TestObject _tbOwnedByUI 属于 UI 线程是错误的,默认情况下没有这样的 concept/behavior 对象。这几乎回答了问题。