2009-06-24 118 views
3

我遇到了多种编程语言中的这个问题,我只是想知道处理它的最佳方法是什么。进行多个异步调用并在完成时执行某些操作

我有三个方法调用异步触发。每个人都有一个回调。只有当所有三个回调都完成后,我才想做点什么。

什么是最好的方式来编码?我通常会得到所有这些公共bool标志,并且随着您添加更多的调用,代码变得更加复杂。

回答

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方法将执行对用于产卵的工人线程池线程,而不是在主线程上......我认为很多其他语言有相似的结构。

+0

我们在什么环境中当调用这个.BeginInvoke?这是什么'? – 2010-08-03 23:03:52

1

如果你真的只需要等待所有完成:

  1. 创建挥发性反
  2. 同步访问计数器上开始
  3. 增加计数器
  4. 减少对回调解雇
  5. 等待计数器达到0
0

期货非常易于使用。期货看起来像正常的功能,只是它们执行异步。

的类:

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()); 
      } 
     } 

+0

这个例子中缺少一些类 – mcintyre321 2009-08-06 09:10:07

相关问题