我在多种编程语言中遇到过这个问题,我只是想知道处理它的最佳方法是什么。
我有三个异步触发的方法调用。每个人都有一个回调。我想只在完成所有三个回调时才做某事。
对此进行编码的最佳方法是什么?我通常最终得到所有这些公共bool标志,当你添加更多调用时,代码会变得更复杂。
答案 0 :(得分:3)
来自C#,我可能会使用WaitHandle.WaitAll
。您可以创建一个ManualResetEvent
对象数组(每个要完成的任务一个),并将该数组传递给WaitAll
。线程任务将分别获得一个ManualResetEvent对象,并在准备好时调用Set
方法。 WaitAll
将阻止调用线程,直到完成所有任务。我将给出一个C#代码示例:
private void SpawnWorkers()
{
ManualResetEvent[] resetEvents = new[] {
new ManualResetEvent(false),
new ManualResetEvent(false)
};
// spawn the workers from a separate thread, so that
// the WaitAll call does not block the main thread
ThreadPool.QueueUserWorkItem((state) =>
{
ThreadPool.QueueUserWorkItem(Worker1, resetEvents[0]);
ThreadPool.QueueUserWorkItem(Worker2, resetEvents[1]);
WaitHandle.WaitAll(resetEvents);
this.BeginInvoke(new Action(AllTasksAreDone));
});
}
private void AllTasksAreDone()
{
// OK, all are done, act accordingly
}
private void Worker1(object state)
{
// do work, and then signal the waiting thread
((ManualResetEvent) state).Set();
}
private void Worker2(object state)
{
// do work, and then signal the waiting thread
((ManualResetEvent)state).Set();
}
请注意,AllTasksAreDone
方法将在用于生成worker的线程池线程上执行,而不是在主线程上执行...我假设许多其他语言具有类似的结构。
答案 1 :(得分:1)
如果您真的只想等待所有完成:
答案 2 :(得分:0)
使用semaphore。
答案 3 :(得分:0)
期货很容易使用。期货看起来像普通函数,除了它们执行asynch。
课程:
public struct FutureResult<T>
{
public T Value;
public Exception Error;
}
public class Future<T>
{
public delegate R FutureDelegate<R>();
public Future(FutureDelegate<T> del)
{
_del = del;
_result = del.BeginInvoke(null, null);
}
private FutureDelegate<T> _del;
private IAsyncResult _result;
private T _persistedValue;
private bool _hasValue = false;
private T Value
{
get
{
if (!_hasValue)
{
if (!_result.IsCompleted)
_result.AsyncWaitHandle.WaitOne();
_persistedValue = _del.EndInvoke(_result);
_hasValue = true;
}
return _persistedValue;
}
}
public static implicit operator T(Future<T> f)
{
return f.Value;
}
}
在这里,我使用期货来模拟死锁:
public struct FutureResult<T>
{
public T Value;
public Exception Error;
}
public class Future<T>
{
public delegate R FutureDelegate<R>();
public Future(FutureDelegate<T> del)
{
_del = del;
_result = del.BeginInvoke(null, null);
}
private FutureDelegate<T> _del;
private IAsyncResult _result;
private T _persistedValue;
private bool _hasValue = false;
private T Value
{
get
{
if (!_hasValue)
{
if (!_result.IsCompleted)
_result.AsyncWaitHandle.WaitOne();
_persistedValue = _del.EndInvoke(_result);
_hasValue = true;
}
return _persistedValue;
}
}
public static implicit operator T(Future<T> f)
{
return f.Value;
}
}
答案 4 :(得分:0)
对于那些使用JavaScript的人,请考虑使用此Stackoverflow问题中讨论的模式: javascript: execute a bunch of asynchronous method with one callback