2011-07-15 61 views
3

我正在使用下面的代碼來啓動一個異步ping的負載。我還有一個由PingCompletedEventHandler調用的函數,該函數將成功ping的地址添加到列表中供以後使用。如何等待所有在C#中完成的異步ping命令?

我想知道一旦所有的ping線程完成後,如何調用一個函數?

public static void PingRange(IPRange range) 
    { 

     foreach (IPAddress ip in range.GetAllIP()) 
     { 
      // Create Pinger 
      AutoResetEvent waiter = new AutoResetEvent(false); 
      Ping pingSender = new Ping(); 
      pingSender.PingCompleted += new PingCompletedEventHandler(pingSender_PingCompleted); 

      // Create a 32 byte data buffer 
      string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 
      byte[] buffer = Encoding.ASCII.GetBytes(data); 

      // Wait 4 seconds for a reply 
      int timeout = 4000; 

      PingOptions options = new PingOptions(64, true); 

      pingSender.SendAsync(ip, timeout, buffer, options, waiter); 
      PingStartCount++; 
     } 
    } 
+0

你可以使用Thread.Join();方法也許如果你把這個方法放到你應該開始的所有線程中。 – Burimi

回答

3

如果您使用的是.NET 4.0,這相當簡單。您可以使用CountdownEvent類而不是PingStartCount計數器和waiter事件。 CountdownEvent將執行兩者的工作。

public static void PingRange(IPRange range) 
{    
    var finished = new CountdownEvent(1); 
    foreach (IPAddress ip in range.GetAllIP()) 
    { 
     finished.AddCount(); // Indicate that a new ping is pending 
     var pingSender = new Ping(); 
     pingSender.PingCompleted += 
      (sender, e) => 
      { 
      finished.Signal(); // Indicate that this ping is complete 
      }; 
     string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 
     byte[] buffer = Encoding.ASCII.GetBytes(data); 
     PingOptions options = new PingOptions(64, true); 
     pingSender.SendAsync(ip, 4000, buffer, options, waiter); 
    } 
    finished.Signal(); // Indicate that all pings have been submitted 
    finished.Wait(); // Wait for all pings to complete 
} 
+1

該解決方案解決了我使用下面的解決方案獲得的奇怪崩潰和藍屏死機。但確實需要稍作更改,請將倒數事件初始化爲1而不是0,並省略第一個AddCount。請參閱[鏈接](http://social.msdn.microsoft.com/Forums/en/parallelextensions/thread/aa49f92c-01a8-4901-9846-91bc1587f3ae) – leinad13

+0

@ leinad13:是的,我通常將它初始化爲1,但我想如果稍微改變它以包含一個額外的'AddCount'調用就會更有意義。我沒有意識到這是行不通的。我會編輯我的答案。感謝您的支持! –

1

簡單的解決辦法是使用PingStartCount變量在pingSender_PingCompleted事件處理程序來跟蹤多少坪仍在等待完成(每個pingSender_PingCompleted被調用時扣除1)。一旦PingStartCount達到0,您將收到所有ping回來。

但是,這並不完全可以證明,因爲當計數器達到0時,您可能仍然在啓動ping過程。爲了確保不是這種情況,需要一個簡單的bool變量,該變量在開始時設置爲false PingRange的結果並且在PingRange結束時允許您檢查ping是否仍在發送。

+0

感謝您的快速解決方案,我是那裏的一部分...與PingStartCount變量。 PingRange中的布爾值正是我所需要的。 – leinad13

+0

或者在循環之前使用單獨的'bool'將'PingStartCount'初始化爲1,每增加一次,每次完成就遞減一次,並在循環之後遞減。如果'PingStartCount'達到0,那麼你知道所有的ping都已經完成**和**,所有的都已經開始。 –

+0

我實現了上述功能,並且第一個調試會話運行正常,並完成了想要的任務。從那以後,我每次嘗試運行程序vshost32.exe在ntdll.dll崩潰,然後我得到一個很好的BSOD(PROCESS_HAS_LOCKED_PAGES)。我試圖鎖定變量,看看是否跨線程正在殺死它 - 但仍然得到藍屏。現在有些東西已經損壞,因爲我每次在VS2010中打開項目Program.cs都會在記事本中打開並且是空白的。 (祝願ID備份) 我將嘗試下面的解決方案。 – leinad13