Wpf 来自';结束了

Wpf 来自';结束了,wpf,multithreading,dependency-properties,invalidoperationexception,Wpf,Multithreading,Dependency Properties,Invalidoperationexception,在WPF应用程序中,我有一个BackgroundWorker线程创建一个对象。让我们把这个对象称为foo 后台工作代码: SomeClass foo = new SomeClass(); // Do some operation on foo // Set some dependency property on the main class to foo this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPost

在WPF应用程序中,我有一个BackgroundWorker线程创建一个对象。让我们把这个对象称为foo

后台工作代码:

SomeClass foo = new SomeClass();
// Do some operation on foo

// Set some dependency property on the main class to foo
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
    (SendOrPostCallback)delegate { SetValue(FooProperty, foo); },
    foo);
现在,当主类尝试使用getter访问FooProperty时,我得到了一个InvalidOperationException:调用线程无法访问该对象,因为它属于另一个线程


如果创建对象的线程已经完成,为什么它仍然拥有该对象?这有什么办法吗?

在给定线程中创建的对象属于该线程。这就是为什么你会得到一个无效手术例外。如果您想在后台线程中设置属性,我建议让委托返回所需的值并从主线程调用SetValue。(创建对象的线程)。

WPF中的绝大多数对象都具有线程关联性。一旦在特定线程上创建了WPF对象,WPF对象将只在从该线程使用时运行。这种限制(与WinForms不同)实际上在您对该对象执行的每个操作上都是强制执行的


您需要更改代码,以便在此场景中在实际UI线程上创建Foo。

假设
SomeClass
是从
DispatcherObject
派生的,创建它的线程运行负责处理
Foo
对象消息的消息泵。因此,如果线程结束,那么对象就不能再处理消息,这不是一个好主意


在大多数情况下,您应该使用相同的UI线程来创建所有UI对象(或从
DispatcherObject
派生的任何其他对象,并确保它在应用程序期间运行。然后使用
Dispatcher
从工作线程向它发送消息。

我尝试在RunWorkerCompleted回调中进行设置,但我需要主线程在构造函数中的某个位置等待直到设置完成。我尝试过执行Handle.WaitOne,但这当然会阻止整个执行,并且RunWorkerCompleted回调永远不会运行。是否有让执行“等待”的最佳实践?是的。所有等待都应该在后台线程中完成。如果构造函数必须等待某个设置完成,我建议将此等待从构造函数中移除(如果可能),并在后台线程中调用它。