开发者

asnychronous callback

开发者 https://www.devze.com 2023-04-12 00:36 出处:网络
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

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
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号