2011-11-03 2 views
2

기존 웹 서비스를 사용하는 서버와 통신하는 데스크탑 응용 프로그램 (.net 3.5)이 있습니다.
웹 서비스 기능을 여러 번 호출하고 모두 끝내기를 기다린 다음 계속해야합니다.모든 비동기 웹 서비스 호출이 반환되기를 기다리는 중

이 호출을 병렬로 수행하고 싶습니다. 그래서 분명히 MyFunctionAsync 메소드를 활용하려고합니다.
문제는 모든 호출이 반환되었는지 확인하는 방법을 모르겠습니다. 여기에 간단한 동기화 메커니즘이 없을 것 같습니다. 이 C#을이처럼

public void DoWork() 
{ 
    service.MyFuncCompleted+= MyFunc_Completed; 
    foreach (var i in items) 
    { 
     service.MyFuncAsync(i); 
     syncMechanism.WaitForAnother(1); //signal that we have to wait for 1 more task to finish 
    } 
    syncMechanism.WaitForAllTasksToFinsih(); //wait until specified number of tasks have finished 

    //continue 
} 

public void MyFunc_Completed(EventArgs e) 
{ 
    //process result... 
    syncMechanism.Signal(1); //signal that 1 task has finished 
} 

아무도 아는 : 여기

내가 할 수 있도록하고 싶습니다 무엇인가?

답변

3

이 포크/조인은 .NET 4에서 훨씬 쉽지만 3.5에서 사용하면 이전 방식을 따라야합니다.

기본적으로 카운터를 하나씩 늘린 다음 처리기에서 카운터를 내림차순으로 낮 춥니 다. 그런 다음 0으로 내려 갔는지 확인하고 대기 핸들을 신호로 보내면 모든 작업이 완료되었음을 나타냅니다. 여기

은 아이디어의 예 :

대신 당신이 쉽게 찾을 수있는 어떤 키가 스레드 ID입니다 내가 해시 맵을 사용하는 간단한 카운터 (또는 웹 서비스 이름, 또는
static ManualResetEvent mre = new ManualResetEvent(false); 
static int inFlight = 1; // start with 1 to fix race condition 

static void DoWork() 
{ 
    for (int i = 0 ; i < 10 ; i++) 
    { 
     var bw = new BackgroundWorker(); 

     bw.DoWork += bw_DoWork; 
     bw.RunWorkerCompleted += bw_RunWorkerCompleted; 

     Interlocked.Increment(ref inFlight); 

     bw.RunWorkerAsync(); 
    } 

    if (Interlocked.Decrement(ref inFlight) == 0) mre.Set(); 

    mre.WaitOne(); // this blocks until all workers have completed 
} 

static void bw_DoWork(object sender, DoWorkEventArgs e) 
{ 
    Thread.Sleep(1000); 
} 

static void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    if (Interlocked.Decrement(ref inFlight) == 0) mre.Set(); 
} 
+1

"0으로 내려 갔는지 확인하십시오."어떻게 제안 하시겠습니까? 바쁘신가요? '(while (true) {if (counter == 0) break;}'? –

+0

답변에 코드 예제를 추가했습니다. –

0

핸들).

값으로 문자열 또는 객체 (호출 시간을 나타냄)를 사용하십시오.

주어진 호출이 반환되면 해시 맵에서 해당 항목을 제거하십시오.

해시 맵이 비어 있으면 계속 진행할 수 있음을 알았습니다. 오랜 시간이 지난 후에 비어 있지 않으면 (기본적으로 호출 콜렉션에 대한 타임 아웃) 해시 맵 내부에서 아직 보류중인 것을 확인하고 얼마나 오래 걸리고 있는지 확인할 수 있습니다.

또는 더 정교한 개체를 값으로 사용하고 원래 타임 스탬프와 함께 실패한 사용자의 반환 코드를 기록 할 수 있습니다 (이 경우 "반환 된 것"보다 완전한 정보가 있음). .

관련 문제