使用TPL对网络中的所有计算机进行Ping操作

时间:2014-07-01 12:06:50

标签: c# network-programming task-parallel-library

我正在开发一个管理网络设备的应用程序,在应用程序的某一点,我必须ping(实际上它不是ping,它是SNMP获取)所有计算机在网络中检查它的类型是否属于我的托管设备。

我的问题是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]);
            }
        }
    }

1 个答案:

答案 0 :(得分:0)

您的问题是您正在迭代无线程安全项List

如果用类似ConcurrentBag的线程安全对象替换它,你会发现线程将并行运行。


我有点困惑为什么这只是运行一个线程,我相信这是这行代码:

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

我认为这会抛出异常并返回;因此你只看到一个线程。这也与您的观察结果有关,如果您添加了睡眠,它可以正常工作。

请记住,当您传递一个字符串时,您将引用传递给内存中的字符串,而不是值。无论如何,ConcurrentBag似乎解决了您的问题。 This answer might also be relevant