2009-06-24 13 views
3

私はこの問題を複数のプログラミング言語で実行しましたが、私はそれを処理する最良の方法が何であるか不思議でした。複数の非同期呼び出しを行い、完了したら何かを実行します

私は非同期的に起動する3つのメソッド呼び出しを持っています。それぞれにコールバックがあります。 3つのコールバックがすべて完了したときにだけ何かしたい。

これをコードする最良の方法は何ですか?私は通常、これらのパブリックブールフラグをすべて終了し、コールを追加するとコードがより複雑になります。

答えて

3

C#からは、おそらくWaitHandle.WaitAllが使用されます。 ManualResetEventオブジェクトの配列を作成し(完了する各タスクに1つずつ)、配列をWaitAllに渡すことができます。スレッド化されたタスクは、それぞれ1つのManualResetEventオブジェクトを取得し、準備ができたらSetメソッドを呼び出します。 WaitAllは、すべてのタスクが完了するまで呼び出しスレッドをブロックします。私はC#のコード例をあげる:AllTasksAreDone方法は、メインスレッド上で労働者を起動するために使用されたスレッドプールのスレッドで実行し、ないことを

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

注意を...私は他の多くのことを前提としてい言語は同様の構造を持っています。

+0

this.BeginInvokeを呼び出すとき?これは何ですか'? –

1

あなたが本当に唯一終了するのすべてのを待ちたい場合:

  1. 揮発性カウンタカウンターへ
  2. 同期アクセスを作成増加カウンタスタート
  3. のコールバックの減少は、
  4. を解雇
  5. カウンタが0に達するのを待つ
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; 
    } 
} 

ここで私はデッドロックをシミュレートするために先物を使用します。JavaScriptを使用してそれらのために


     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

関連する問題