So let's say I have a method such as ThreadPool.QueueTask(Delegate d).
Some of these delegates need to return values, but as they cannot do this (being passed as delegates) they will need to take a value by reference as a parameter. Once the task is completed this value will have been altered, so the calling method needs to know this.
Essentially, the method passing the task to the threadpool should be waiting until it has completed.
What is the best way to do this? Should I just do Threadpool.QueueTask(Delegate d, EventWaitHandle e), or is there a more elegant way which would be obvious to people unfamiliar with t开发者_如何学Pythonhat kind of thing?
Kind regards, Fugu
You can use a ManualResetEvent:
public void TaskStartMethod()
{
ManualResetEvent waitHandle = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(o=>
{
// Perform the task here
// Signal when done
waitHandle.Signal();
});
// Wait until the task is complete
waitHandle.WaitOne();
}
Essentially, the method passing the task to the threadpool should be waiting until it has completed.
The above code does that, but now I have a question: if your method is waiting for the task to be completed, then why do you even bother to perform the task on a separate thread? In other words, what you're describing is sequential execution of code rather than parallel, so the use of the ThradPool
is pointless.
Alternately, you might might want to use a separate delegate as a callback:
public delegate void OnTaskCompleteDelegate(Result someResult);
public void TaskStartMethod()
{
OnTaskCompleteDelegate callback = new OnTaskCompleteDelegate(OnTaskComplete);
ThradPool.QueueUserWorkItem(o=>
{
// Perform the task
// Use the callback to notify that the
// task is complete. You can send a result
// or whatever you find necessary.
callback(new Result(...));
});
}
public void OnTaskComplete(Result someResult)
{
// Process the result
}
Update (1/24/2011):
You might not even need the callback delegate, you can just directly call OnTaskComplete
and that should do the job too:
public void TaskStartMethod()
{
ThradPool.QueueUserWorkItem(o=>
{
// Perform the task
// Call the method when the task is complete
OnTaskComplete(new Result(...));
});
}
Depends on how you are doing it. To me it sounds a little like you have thread A putting a single task on the thread pool, then waiting for that to finish. That does not sound very helpful. If you are putting one task on the thread pool and waiting, just do it in your own thread.
But that is probably not what your doing!
I can see two possible good ways for using the thread pool. Thread A has multiple things that it wants to kick off in parallel, and then wait for them all to finish. In this case you need to store a handle to all of the tasks (or a result class), so you can wait for them all to finish. You can make use of semiphores or various synchronization tools (I don't do c# specifically) to avoid having to busy poll.
Another way is to use a callback at the end of the task. Thread A kicks off the task on the thread pool, then exists. The task has a handle back to the class that kicked it off, and calls a callback type function when it is completed to do finalisation type stuff.
精彩评论