2011-11-03 101 views
2

我有一個桌面應用程序(.net 3.5),它使用經典Web服務與服務器進行通信。
我需要對Web服務功能進行多次調用,等待它們全部完成,然後繼續。等待所有異步Web服務調用返回

我想同時進行這些調用;所以顯然我正在尋求利用MyFunctionAsync方法。
事情是 - 我不知道如何驗證所有電話已返回。我可能在這裏錯過了一些簡單的同步機制。

這是我想怎麼能夠做到:

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 
} 

有人知道這樣的事是C#?

回答

3

在.NET 4中,這個(fork/join)要容易得多,但是你在3.5上,所以你必須以老式的方式來完成。

基本上,爲每個操作增加一個計數器,然後在你的Completed處理程序中遞減計數器。然後檢查它是否歸零,如果是,則發出一個等待句柄來指示所有操作已完成。

這裏的想法的一個例子:

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

「檢查它是否降到零」:你會如何建議這樣做?忙等待? '(while(true){if(counter == 0)break;}'? –

+0

我已經給我的答案添加了一個代碼示例 –

0

而不是一個簡單的計數器,我會用一個HashMap。其中,關鍵是線程ID(或Web服務的名稱,或任何你能找到簡單的處理)。

作爲一個值使用字符串或對象(表示調用時間)。

當給定的調用返回時,從hashmap中刪除相應的項目。

當散列表爲空時,您知道您可以繼續。 如果在很長一段時間之後它不是空的(這基本上是您所做的調用收集的超時),您可以在散列圖內部檢查哪一個仍處於待定狀態,以及需要多長時間。

或者,您可以使用更復雜的對象作爲值,並記錄原始時間戳以及失敗者的返回碼(在這種情況下,您的信息比「返回」更完整) 。