asnychronous callback
本文关键字:callback asnychronous | 更新日期: 2023-09-27 18:11:01
我是异步编程新手。我有一个c# dll与一个异步方法被调用,接受一个函数指针(委托),并在"结果"计算后调用这个回调函数。
public delegate void CreatedDelegate(Foo result);
public void CreateAsync(CreatedDelegate createdCallback)
{
Task t = Task.Factory.StartNew(() =>
{
Foo result = ...
createdCallback(result);
});
}
"CreatedDelegate"类型的委托回调(在我的情况下)是一个函数指针,指向一个c++/CLI方法,与结果一起工作。
void CreatedCallback(Foo^ result)
{
// do something with result
}
所以这个异步的概念似乎在大多数情况下工作得很好,但有时我遇到一些错误。我怎么能实现它,如果函数"CreateAsync"被调用多次不同的计算努力,结果调用"CreatedCallback"只是发生在相同的顺序,原来"CreateAsync"被调用?为了使它更清晰:第一次调用"CreateAsync"应该导致第一次调用"CreatedCallback",即使后续调用"CreateAsync"更快,实际上会更早调用回调。
也许这可以通过只允许一个活动的新线程在异步"CreateAsync"在一个时间?
要按顺序处理回调,您将需要实现一些工作项排队。最简单的方法可能是使用BlockingCollection
类型(请参阅MSDN文档)。
您的CreateAsync
方法将不调用回调,而是将任务(连同回调)添加到队列中:
// 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));
// ..
}
这只会向队列中添加任务和回调——要真正调用回调,您需要另一个任务来等待队列中的任务(按照它们被添加的顺序)并调用回调:
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);
}
}
如果顺序很重要,那么使用线程可能更好:
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