2014-07-01 124 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