我遇到了多种编程语言中的这个问题,我只是想知道处理它的最佳方法是什么。进行多个异步调用并在完成时执行某些操作
我有三个方法调用异步触发。每个人都有一个回调。只有当所有三个回调都完成后,我才想做点什么。
什么是最好的方式来编码?我通常会得到所有这些公共bool标志,并且随着您添加更多的调用,代码变得更加复杂。
我遇到了多种编程语言中的这个问题,我只是想知道处理它的最佳方法是什么。进行多个异步调用并在完成时执行某些操作
我有三个方法调用异步触发。每个人都有一个回调。只有当所有三个回调都完成后,我才想做点什么。
什么是最好的方式来编码?我通常会得到所有这些公共bool标志,并且随着您添加更多的调用,代码变得更加复杂。
来自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
方法将执行对用于产卵的工人线程池线程,而不是在主线程上......我认为很多其他语言有相似的结构。
如果你真的只需要等待所有完成:
使用semaphore。
期货非常易于使用。期货看起来像正常的功能,只是它们执行异步。
的类:
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;
}
}
这里我用期货来模拟一个僵局:
void SimulateDeadlock()
{
Future> deadlockFuture1 = new Future>(() =>
{
try
{
new SystemData(ConfigurationManager.ConnectionStrings["DbConnectionString"].ConnectionString)
.SimulateDeadlock1(new DateTime(2000, 1, 1, 0, 0, 2));
return new FutureResult { Value = true };
}
catch (Exception ex)
{
return new FutureResult { Value = false, Error = ex };
}
});
Future> deadlockFuture2 = new Future>(() =>
{
try
{
new SystemData(ConfigurationManager.ConnectionStrings["DbConnectionString"].ConnectionString)
.SimulateDeadlock2(new DateTime(2000, 1, 1, 0, 0, 2));
return new FutureResult { Value = true };
}
catch (Exception ex)
{
return new FutureResult { Value = false, Error = ex };
}
});
FutureResult result1 = deadlockFuture1;
FutureResult result2 = deadlockFuture2;
if (result1.Error != null)
{
if (result1.Error is SqlException && ((SqlException)result1.Error).Number == 1205)
Console.WriteLine("Deadlock!");
else
Console.WriteLine(result1.Error.ToString());
}
else if (result2.Error != null)
{
if (result2.Error is SqlException && ((SqlException)result2.Error).Number == 1205)
Console.WriteLine("Deadlock!");
else
Console.WriteLine(result2.Error.ToString());
}
}
这个例子中缺少一些类 – mcintyre321 2009-08-06 09:10:07
对于使用JavaScript的那些,可以考虑使用这个#1问题讨论的模式: javascript: execute a bunch of asynchronous method with one callback
我们在什么环境中当调用这个.BeginInvoke?这是什么'? – 2010-08-03 23:03:52