2014-07-01 123 views
2

我正在開發一個管理網絡中設備的應用程序,在應用程序中的某個點,我必須ping(實際上它不是ping,它是一個SNMP get)所有計算機網絡來檢查它的類型是否屬於我的受管設備。在TPL網絡中Ping所有計算機

我的問題是,ping網絡中的所有計算機是非常慢的(特別是因爲他們中的大多數不會響應我的消息,並會簡單地超時),並且必須異步完成。

我試圖用TLP用下面的代碼來做到這一點:

public static void FindDevices(Action<IPAddress> callback) 
{ 
    //Returns a list of all host names with a net view command 
    List<string> hosts = FindHosts(); 

    foreach (string host in hosts) 
    { 
     Task.Run(() => 
     { 
      CheckDevice(host, callback); 
     }); 
    } 
} 

但運行速度很慢,當我暫停執行我檢查線程窗口,看到它只有一個線程PING網絡並因此同步運行任務。

當我使用普通線程時,運行速度要快很多,但任務應該會更好,我想知道爲什麼我的任務不是優化並行性。

**編輯** 意見要求對CheckDevice代碼,所以這裏有雲:

private static void CheckDevice(string host, Action<IPAddress> callback) 
    { 
     int commlength, miblength, datatype, datalength, datastart; 
     string output; 
     SNMP conn = new SNMP(); 


     IPHostEntry ihe; 
     try 
     { 
      ihe = Dns.Resolve(host); 
     } 
     catch (Exception) 
     { 
      return; 
     } 
     // Send sysLocation SNMP request 
     byte[] response = conn.get("get", ihe.AddressList[0], "MyDevice", "1.3.6.1.2.1.1.6.0"); 

     if (response[0] != 0xff) 
     { 
      // If response, get the community name and MIB lengths 
      commlength = Convert.ToInt16(response[6]); 
      miblength = Convert.ToInt16(response[23 + commlength]); 

      // Extract the MIB data from the SNMP response 
      datatype = Convert.ToInt16(response[24 + commlength + miblength]); 
      datalength = Convert.ToInt16(response[25 + commlength + miblength]); 
      datastart = 26 + commlength + miblength; 
      output = Encoding.ASCII.GetString(response, datastart, datalength); 
      if (output.StartsWith("MyDevice")) 
      { 
       callback(ihe.AddressList[0]); 
      } 
     } 
    } 
+0

這可能取決於CheckDevice實際做了什麼 – Liam

+2

另外一個List不是線程安全的,不應該被使用。 [你應該使用ConcurrentBag](http://stackoverflow.com/questions/5874317/thread-safe-listt-property)。這可能是你問題的根源。 CheckDevice有沒有機會鎖定它? – Liam

+0

發佈「CheckDevice」的代碼 –

回答

0

您的問題是,你是一個迭代沒有線程安全的項目List

如果將其替換爲像ConcurrentBag這樣的線程安全對象,應該會發現線程將並行運行。


我有點困惑,爲什麼這只是運行一個線程,我相信它是這行代碼:

try 
{ 
    ihe = Dns.Resolve(host); 
} 
catch (Exception) 
{ 
    return; 
} 

我認爲這是拋出異常和返回;因此你只能看到一個線程。這也與你的觀察相關,如果你增加了睡眠,它就能正常工作。

請記住,當您傳遞一個字符串時,將對該字符串的引用傳遞給內存,而不是該值。無論如何,ConcurrentBag似乎可以解決您的問題。 This answer might also be relevant

+0

Dns。解決(主機);在超時後拋出一個異常,所以我仍然看到線程在替換爲ConcurrentBag後在該行停止,從測試我會說TPL以某種方式檢測到我正在從非線程安全結構訪問成員並序列化確保預測結果的任務。 –

+0

另外,Dns.Resolve(host);不是我用睡眠取代的線,它是CheckDevice(主機,回調);從而使主機變量變爲未使用 –

+0

但CheckDevice調用Resolve?此外,解析是您使用字符串主機的唯一要點。這完全是同一個問題。引用類型正在任務外移動。這可能會導致Resolve失敗或以不安全的方式更新列表。拋出異常的類型是什麼? – Liam