Threading Advice Quick Question

  • Thread starter Thread starter Mark
  • Start date Start date
M

Mark

Hi I have a non UI set of classes which do bits and pieces like getting
file lists, generating xml etc. I figured on doing some of these
processes on seperate threads. These wouldnt be called by the UI they
would be controlled by the objects themselves. My question is simply
whats the correct way to notify completion back to the object that
called it. I have used control.invoke in the past but the objects arent
controls as such although I could make them I guess. Just looking for
some advice on best practice.

Cheers
 
Hi I have a non UI set of classes which do bits and pieces like getting
file lists, generating xml etc. I figured on doing some of these
processes on seperate threads. These wouldnt be called by the UI they
would be controlled by the objects themselves. My question is simply
whats the correct way to notify completion back to the object that
called it. I have used control.invoke in the past but the objects arent
controls as such although I could make them I guess. Just looking for
some advice on best practice.

If your classes are general non-UI classes that performs asyncronous
operations (let's call these classes the business layer) and notify the
client of their completion via callback methods then the clients of these
classes should expect these callbacks to be called in a worker thread and
take appropriate steps to deal with it. This is how all the classes in the
..NET Framework that provide asyncronous methods do it (they have BeginXXX
methods that take an AsyncCallback delegate and they invoke the callback
method in a thread from the thread pool). In other words, it is in your UI
layer that you should marchall the callback method to the UI thread if you
need to access any UI control. Your business layer does not have any
knowledge of the constraints of the UI when it comes to multi-threading and
should not bother about it.

Now, if you really want to interleave the UI and the business layers, you
could pass a Control object in the constructor of your business classes
allowing them to call Invoke() or BeginInvoke() on it in order to invoke
their callback methods in the UI thread.
 
Hi Mehdi,

You can do this by using a Delegate, just invoke the delegate after
finishing the work.
The method pointed to by the delegate can be in the same class where you do
the work.

Hope this helps.
 
Mark said:
Hi I have a non UI set of classes which do bits and pieces like getting
file lists, generating xml etc. I figured on doing some of these
processes on seperate threads. These wouldnt be called by the UI they
would be controlled by the objects themselves. My question is simply
whats the correct way to notify completion back to the object that
called it. I have used control.invoke in the past but the objects arent
controls as such although I could make them I guess. Just looking for
some advice on best practice.

Cheers


Here's the thread class i wrote to support callback. Its imple and esay
to extend if needed:

namespace MySystem
{
public delegate void MyThreadStart();
public class MyThread
{
public event EventHandler ThreadFinished;
protected MyThreadStart m_tsThreadStart;
public MyThread(MyThreadStart tsThreadStart)
{
m_tsThreadStart = tsThreadStart;
}

public void Start()
{
m_tsThreadStart.BeginInvoke(new AsyncCallback(CallBack), null);
}

private void CallBack(IAsyncResult res)
{
if (ThreadFinished != null)
ThreadFinished(this, EventArgs.Empty);
}
}
}

And when you create that thread object you just subscribe to its
ThreadFinished event which will fire when the thread is done.

One note: maybe i'm mistaken but i think that callback will fire in
context of that worker thread - just something to be aware of especially
if you deal with UI.

Hope it helps,
MuZZy
 
Here's the thread class i wrote to support callback. Its imple and esay
to extend if needed: [...]
public delegate void MyThreadStart();
public class MyThread
{
protected MyThreadStart m_tsThreadStart; [...]
public void Start()
{
m_tsThreadStart.BeginInvoke(new AsyncCallback(CallBack), null);
} [...]

And when you create that thread object you just subscribe to its
ThreadFinished event which will fire when the thread is done.

There's like a problem with your helper class. Typically, when somebody
wants to create their own thread instead of using a thread from the
ThreadPool (which is much more efficient), this is because they want to do
some long running operation. Doing a long running operation in a thread
taken from the ThreadPool is a no-no as you might end up starving the
ThreadPool. Yet, that's what you are doing in your class:

m_tsThreadStart.BeginInvoke(new AsyncCallback(CallBack), null);

Calling BeginInvoke() on a delegate doesn't create a new thread but causes
the fonction represented by the delegate to be executed in a thread from
the ThreadPool. This wouldn't be a problem if you made it clear that your
Start() method actually invoked the supplied delegate in a thread from the
ThreadPool and *not* from a new thread. But instead, you have given your
class the very misleading name "MyThread" which leads users to think that
this is just a wrapper for the Thread class; the name of its event
("ThreadFinished") adds to the confusion. I think that you should either
create a new thread in your Start() method instead of using the ThreadPool
or rename your class and make it very clear in the doc and explanation that
your class uses the ThreadPool to invoke to supplied delegate.
 
Easiest way to do this is to wrap your current calculation or data-bound
methods with a delegate. Call BeginInvoke on the delegate and pass a
delegate to a method that will be called upon completion of the asynchronous
method. In this method, call EndInvoke to retrieve the results of the async
op. I wrote a little article for CodeProject about it:

http://www.codeproject.com/useritems/Async_Ops_and_Delegates.asp

Check out the code for the third rendezvous technique. It shows you how to
handle EndInvoke properly. I'd also suggest you get 'CLR Via C#', which has
lots of good info about asynchronous ops and the various pitfalls you face
when using them.
 
Back
Top