Thread

M

mehdi

Hi folks,
Consider a class (MyClass) in which one of its methods (named Run) is
supposed to run in another thread, rather than the Main thread. This
class uses the System.Threading.Thread class to get the job done.
Here's the pseudo code:

class MyClass
{
void ExecAsync()
{
Start a given worker thread, say, myThreadProc.
}

void myThreadProc()
{
Run(); //An abstract method.
Fire the events, either the canceled or completed operation...
}

void Cancel()
{
//wait until the thread quits.
}
}

The question is that I've got no idea how to fire those events in the
main thread context. Any idea?

TIA,
Mehdi
 
P

Peter Duniho

The question is that I've got no idea how to fire those events in the
main thread context. Any idea?

Generally speaking, if you have no other design restrictions or goals,
Invoke or BeginInvoke are useful for signaling the GUI (main) thread.

Pete
 
M

Marc Gravell

One route is to pass an ISynchronizeInvoke to your class, which is the
approach used by System.Timers.Timer.

In simple terms, this means you can pass a form / control to your
class, and it will fire events back through the UI thread. Other sync
providers may be available ;-p

Marc



using System;
using System.ComponentModel;
using System.Threading;

static class Program
{
static void Main()
{ }
}

public abstract class ThreadedExample
{
private readonly ISynchronizeInvoke _syncInvoke;
public ThreadedExample() : this(null) { }
public ThreadedExample(ISynchronizeInvoke sync)
{
_syncInvoke = sync;
}

public event EventHandler Completed, Cancelled;
protected abstract bool Run();
public void MainMethod()
{
ThreadPool.QueueUserWorkItem(ThreadStart);
}
public void ThreadStart(object state)
{
bool success = Run();
OnEvent(success ? Completed : Cancelled, true);
}
protected void OnEvent(EventHandler handler, bool async)
{
if (handler != null)
{
if (_syncInvoke == null)
{ // no sync context; have to run sync
handler(this, EventArgs.Empty);
}
else if (async)
{
_syncInvoke.BeginInvoke(handler, new object[] { this,
EventArgs.Empty });
}
else
{
_syncInvoke.Invoke(handler, new object[] { this,
EventArgs.Empty });
}
}
}
}
 
M

Marc Gravell

Of course, as Peter observes, a simpler approach can be to simple fire
the events on the current thread, and make it clear to the caller that
the event will fire on an arbitrary thread and that they must
therefore deal with sync themselves locally - e.g. by using
InvokeRequired / BeginInvoke / Invoke at the caller ;-p

Additional note: using the synchronizing object approach (my last
post) you could also test InvokeRequired before firing the event -
e.g. the first block would become (leaving the rest unchanged):

if (_syncInvoke == null || !_syncInvoke.InvokeRequired)
{ // no sync context (have to run sync) or synchronize not
necessary
handler(this, EventArgs.Empty);
}

Marc
 
M

mehdi

Of course, as Peter observes, a simpler approach can be to simple fire
the events on the current thread, and make it clear to the caller that
the event will fire on an arbitrary thread and that they must
therefore deal with sync themselves locally - e.g. by using
InvokeRequired / BeginInvoke / Invoke at the caller ;-p

Additional note: using the synchronizing object approach (my last
post) you could also test InvokeRequired before firing the event -
e.g. the first block would become (leaving the rest unchanged):

if (_syncInvoke == null || !_syncInvoke.InvokeRequired)
{ // no sync context (have to run sync) or synchronize not
necessary
handler(this, EventArgs.Empty);
}

Marc

Well, I really enjoyed the ISynchronizeInvoke interface. However, I'm
still confused about the provided code.

1. What if I never ever call the "Invoke" method?
2. What exactly Control.BeginInvoke does?
3. What does Control.EndInvoke do? Is is just supposed to get the
return value of an asynchronous function?

Any help would be highly appreciated,

Cheers,
Mehdi
 
M

Marc Gravell

(which incidentally is the top entry on a google search of
"Control.BeginInvoke"; just a thought...)

Marc
 
M

mehdi

Well, I really enjoyed the ISynchronizeInvoke interface. However, I'm
still confused about the provided code.

1. What if I never ever call the "Invoke" method?
2. What exactly Control.BeginInvoke does?
3. What does Control.EndInvoke do? Is is just supposed to get the
return value of an asynchronous function?

Any help would be highly appreciated,

Cheers,
Mehdi

For those who are familiar with Win32, the short answer is that
Control.BeginInvoke actually calls the PostMessage API, while the
Invoke method calls the SendMessage API.

HTH,
Mehdi
 

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