了解哪个对象由哪个线程拥有
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()
手动保护此对象上的所有操作免受跨线程调用,如果调用线程不同于“所有者”线程,则会抛出异常。
例如,您可以通过从 DispatcherObject
派生并保护 Data
属性 [=36] 在 TestObject
class 中实现相同的行为=] 和 setter 与 VerifyAccess()
.
最后,你假设 TestObject _tbOwnedByUI
属于 UI 线程是错误的,默认情况下没有这样的 concept/behavior 对象。这几乎回答了问题。
尝试从另一个线程访问 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()
手动保护此对象上的所有操作免受跨线程调用,如果调用线程不同于“所有者”线程,则会抛出异常。
例如,您可以通过从 DispatcherObject
派生并保护 Data
属性 [=36] 在 TestObject
class 中实现相同的行为=] 和 setter 与 VerifyAccess()
.
最后,你假设 TestObject _tbOwnedByUI
属于 UI 线程是错误的,默认情况下没有这样的 concept/behavior 对象。这几乎回答了问题。