views:

141

answers:

3

In a WPF application I had a BackgroundWorker thread creating an object. Let's call the object foo.

Background worker code:

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);

Now, when the main class tries to access FooProperty using a getter, I get an InvalidOperationException: The calling thread cannot access this object because a different thread owns it.

If the thread the create the object is finished, why does it still own the object? Is there someway around this.?

+1  A: 

An object you create in a given thread is owned by that thread. That's why you're getting an InvalidOperationException. If you would like to set a property in a background thread, I recommend having the delegate return the desired value and calling SetValue from your main thread. (thread that created the object).

helios456
I tried doing the setting in the RunWorkerCompleted callback, but I need the main thread to wait at a certain spot in a constructor until the setting has been done. I tried doing Handle.WaitOne, but of course that blocks the entire execution and the RunWorkerCompleted callback is never run. Would there be a best practice for making the execution "wait"?
Bob
Your right. All waits should be done in the background thread. If the constructor has to wait for a certain setting to be done, I would suggest taking this wait out of the constructor (if possible) and calling it in your background thread.
helios456
+1  A: 

The vast majority of objects in WPF have thread affinity. That is once created on a particular thread, a WPF object will then only operate when used from that thread. This restriction is enforced (unlike WinForms) on practically every operation you do on that object.

You will need to change your code to have Foo created on the actual UI thread for this scenario.

JaredPar
+1  A: 

Assuming SomeClass is derived from DispatcherObject, the thread that created it runs the message pump that is responsible for processing messages for the foo object. Therefore if that thread ends then the object can no longer process messages, which isn't a good idea.

In most situations you should use the same UI thread to create all of your UI objects (or anything else that is derived from DispatcherObject and make sure it runs for the duration of your application. Then use the Dispatcher to send messages to it from your worker threads.

GraemeF