BeginInvoke async callback

N

nick_tucker

Is The following Code valid it is like a mini thread pool(a friend at
work wrote it)?
I have cut down the code a bit but kept the essential parts.
The main part that I am would like explainedis when the async callback
gets called and the the line
m_WaitCallback.EndInvoke(AsyncResult);
How does it know which method has ended. i.e. does the AsyncResult
identify it?? Is it accepable to have one member variable used for all
of the begininvoke calls.

Thanks for any help,
Nick

public class SerialisedWorkerQueue
{
private WaitCallback m_WaitCallback;

private Queue m_Queue;
private int m_AvailableThreads;
private int m_ThreadsInUse;

public SerialisedWorkerQueue()
{
m_WaitCallback=new WaitCallback
(PerformWork_Internal);
m_Queue=new Queue();
m_AvailableThreads=5;
m_ThreadsInUse=0;
}

public void Add(object WorkerItem)
{
m_Queue.Enqueue(WorkerItem);
if (m_ThreadsInUse<m_AvailableThreads)
SpawnWork(null);
}

private void SpawnWork(IAsyncResult AsyncResult)
{
lock(this)
{
if(AsyncResult!=null)
{
m_WaitCallback.EndInvoke(AsyncResult);
m_ThreadsInUse--;
}

// oWorker item will be null if the queue was empty
if(m_Queue.Count>0)
{
m_ThreadsInUse++;

//Gets the next piece of work to perform
object oWorkerItem = m_Queue.Dequeue();
//Hooks up the callback to this method.
AsyncCallback oAsyncCallback = new AsyncCallback(this.SpawnWork);
//Invokes the work on the threadpool
m_WaitCallback.BeginInvoke(oWorkerItem,oAsyncCallback,null);
}
}
}

private void PerformWork_Internal(object WorkerItem)
{
//Do Work...
}
}
 
W

Wessel Troost

m_WaitCallback.EndInvoke(AsyncResult);
How does it know which method has ended. i.e. does the AsyncResult
identify it??

Note that SpawnWork() is passed as information to the BeginInvoke() call.
That means it will be called as an event handler when the asynchronous
method is done. The parameter AsyncResult indeed identifies the method
which has ended.
Is it accepable to have one member variable used for all
of the begininvoke calls.
I think (not sure) that WaitCallback is just a delegate pointing to
PerformWork_Internal. It would be OK to reuse that information, so one
member variable is ok.

Greetings,
Wessel
 
N

Nicholas Paldino [.NET/C# MVP]

Nick,

This is what the last parameter (or second to last parameter) on the
call to BeginInvoke is for. It allows you to pass a state to the method
which you can retrieve from the IAsyncResult implementation passed to your
callback which allows you to identify which method you called, as well as
any other state information you would need.

You could use one member variable for all of the BeginInvoke calls, but
depending on the implementation, it might or might not be allowed (you might
have to match it up with the appropriate instance, or not).

Hope this helps.
 
N

nick_tucker

Thanks for your replys, Just one more question then would I be able to
do the following:

SerialisedWorkerQueue swq = new SerialisedWorkerQueue()
swq.Add(null);
swq.Add(null);
swq.Add(null);

and expect it to *always* work OK??


Thanks again
 
N

Nicholas Paldino [.NET/C# MVP]

Nick,

No, I wouldn't, because you don't have anything in the Add method that
is serializing access to the collection.
 
N

nick_tucker

Missed out the lock. so this would make the above question work??

public void Add(object WorkerItem)
{
lock(this)
{
m_Queue.Enqueue(WorkerItem);
if (m_ThreadsInUse<m_AvailableThr­eads)
SpawnWork(null);
}
}
 
N

Nicholas Paldino [.NET/C# MVP]

I would think that the lock needs to be in the SpawnWork method.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Missed out the lock. so this would make the above question work??

public void Add(object WorkerItem)
{
lock(this)
{
m_Queue.Enqueue(WorkerItem);
if (m_ThreadsInUse<m_AvailableThr­eads)
SpawnWork(null);
}
}
 

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