Marshalling to a particular thread

P

Peter Wone

I've written a class which does some long running background processing and
returns multiple results via events. The class has an Execute() method which
creates a thread and runs an internal method _execute() on it.

When events fire they are running on the worker thread. To use this class
from a form with event handlers that manipulate the UI, you have to write
this

public void MyForm_DocumentReady(object Sender, DocumentReadyEventArgs e) {
if (InvokeRequired)
Invoke(new DocumentReadyDelegate(MyForm_DocumentReady), new object[]
{Sender, e);
else {
//do stuff on UI thread
}
}

But I can't expect people to know they have to do that!

Invoke() searches for the root windowed parent of the control on which it is
invoked, and marshals to that thread. If I made the class a derivative of
Control I could do the marshalling internally using Invoke. But this class
won't necessarily be a parented control.

Getting a reference to the thread that calls Execute() is easy. You just
take snaffle a reference to the current thread when entering the Execute()
method. Can anyone tell me how to say, "run this method on that thread"
without using Invoke?
 
T

Truong Hong Thi

Hi Peter,

You can try the approach used by System.IO.FileSystemWatcher class. It
has a property called SynchronizingObject which, if set, is used to
marshall the event handler calls.
But I can't expect people to know they have to do that!
Then they have to set SynchronizingObject to "this". You can see that
in the form designer, when you drag a FileSystemWatcher into a form,
its SynchronizingObject is default to "this".

Regards,
Thi
 
J

Jon Skeet [C# MVP]

Peter said:
Getting a reference to the thread that calls Execute() is easy. You just
take snaffle a reference to the current thread when entering the Execute()
method. Can anyone tell me how to say, "run this method on that thread"
without using Invoke?

No - there's no such concept, as the thread which you want to run the
method on has to actively be looking for things to run. You can't just
interrupt it and tell it to do something.

A better solution would be to use an ISynchronizeInvoke object which
had to be passed in on construction (or on the call to Execute, or
whatever) if synchronization was required. If UI code wanted to execute
events on the UI thread, it could just pass a control in (as Control
implements ISynchronizeInvoke). Other code may wish to marshall to the
consumer of a queue, for instance, by placing the work item on the
queue being consumed. ISynchronizeInvoke is the .NET interface designed
for just this task.

Jon
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top