我遇到了多種編程語言中的這個問題,我只是想知道處理它的最佳方法是什麼。進行多個異步調用並在完成時執行某些操作
我有三個方法調用異步觸發。每個人都有一個回調。只有當所有三個回調都完成後,我纔想做點什麼。
什麼是最好的方式來編碼?我通常會得到所有這些公共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