I am new to asynchronous programming. I have a C# dll with an asynchro开发者_Python百科nous method that gets called, takes a function pointer (delegate) and calls this callback function after "result" is calculated.
public delegate void CreatedDelegate(Foo result);
public void CreateAsync(CreatedDelegate createdCallback)
{
Task t = Task.Factory.StartNew(() =>
{
Foo result = ...
createdCallback(result);
});
}
The delegate callback of type "CreatedDelegate" is (in my case) a function pointer to a C++/CLI method that works with the result.
void CreatedCallback(Foo^ result)
{
// do something with result
}
So this asynchronous concept seems to work quite well in most cases, but sometimes I encounter some errors. How can I achieve it if the function "CreateAsync" is called multiple times with different computation effort, that the resulting calls to "CreatedCallback" just happen in the same order as originally "CreateAsync" was called? To make it clearer: The first call to "CreateAsync" should result in the first call to "CreatedCallback" even if a succeeding call of "CreateAsync" is faster and would actually call the callback earlier.
Maybe this can be done by allowing only one active new thread in the asynchronous "CreateAsync" at a time?
To process the callbacks in order, you'll need to implement some queueing of work items. The easiest way is probably to use BlockingCollection
type (see MSDN documentation).
Instead of calling the callback, your CreateAsync
method would add the task (together with the callback) to the queue:
// Queue to keep tasks and their callbacks
private BlockingCollection<Tuple<Task<Foo>, CreatedDelegate>>
queue = new BlockingCollection<Tuple<Task<Foo>, CreatedDelegate>>()
public void CreateAsync(CreatedDelegate createdCallback) {
Task<Foo> t = Task.Factory.StartNew(() => {
Foo result = ...
return result; });
queue.Add(Tuple.Create(t, createdCallback));
// ..
}
This will only add tasks and callbacks to the queue - to actually call the callback, you'll need another task that waits for the tasks in the queue (in the order in which they were added) and calls the callback:
Task.Factory.StartNew(() => {
while(true) { // while you keep calling 'CreateAsync'
// Get next task (in order) and its callback
Tuple<Task<Foo>, CreatedDelegate> op = queue.Take();
// Wait for the result and give it to callback
op.Item2(op.Item1.Result);
}
}
If order is important, then using Threads might be better:
thread queue = empty
for each task
{
if there are no free 'cpu'
wait on first thread in queue
remove thread from queue
call delegate
create thread
add thread to queue
}
while queue has threads
wait on first thread in queue
remove thread from queue
call delegate
精彩评论