2009-06-24 5 views
3

여러 프로그래밍 언어에서이 문제가 발생했으며이를 처리하는 가장 좋은 방법은 무엇인지 궁금합니다.여러 비동기 호출 만들기 및 완료시 작업 수행

나는 비동기 적으로 시작되는 세 가지 메소드 호출을 가지고있다. 각각은 콜백을 가지고있다. 세 가지 콜백이 모두 완료되었을 때만 무언가를하고 싶습니다.

코드를 작성하는 가장 좋은 방법은 무엇입니까? 나는 보통이 모든 공개 bool 플래그로 끝나고 더 많은 호출을 추가하면 코드가 더 복잡하게됩니다.

답변

3

C#에서 오는 것입니다. 아마 WaitHandle.WaitAll을 사용할 것입니다. ManualResetEvent 개체의 배열 (완료 할 각 작업마다 하나씩)을 만들고 해당 배열을 WaitAll으로 전달할 수 있습니다. 스레드 작업은 각각 하나의 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

어떤 문맥입니까? 이걸 부를 때 .BeginInvoke? '이것'은 무엇입니까? –

1

당신이 정말로에만 완료 모든 대기하려면 : 시작에

  • 증가 카운터에 대응하기 위해

    1. 하는 휘발성 카운터를 만들기
    2. 동기화 액세스를
    3. 콜백에
    4. 감소는
    5. 을 발사
    6. 카운터가 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; 
        } 
    } 
    

    : 자바 스크립트를 사용하는 사람들을 위해

    
         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