C#Ping-Class - 如果连接错误,取消Ping.Send()

时间:2018-06-07 08:40:37

标签: c# excel server ping hostname

我构建了一个简单的程序,它包含一个包含一组服务器主机名的excel列表,并对每个服务器主机名执行ping操作,并在控制台中返回结果,其中有多少主机在线。

我正在使用try / catch块来防止应用程序在主机名未知时崩溃(出现连接错误时)。

现在我正在寻找一个解决方案,在连接错误时跳过ping请求,因此程序继续ping下一个主机名,程序可以更快地完成而无需等待异常发生。

这就是我现在正在使用的代码。

foreach (var server in serverList)
{        
     try
     {
         var reply = pingSender.Send(server, 1000);              

         //if server is reachable
         if (reply.Status == IPStatus.Success)
         {
             //add server to new excel and display it as online
             onlineList.Cells[serverCount, 1] = server + " is online";
             //increase counters
             serverCount++;
             onlineCount++;
         }
         else
         {
             //add server to new excel and display it as offline
             onlineList.Cells[serverCount, 2] = server + " is offline or unreachable.";                        
             serverCount++;
         } 
     }
     catch (Exception)
     {
         //if in any case the destination is unknown and prevent application from crashing
         onlineList.Cells[serverCount, 2] = server + " is offline or unreachable.";
         serverCount++;             
     }       
 }

1 个答案:

答案 0 :(得分:0)

问题是你一个接一个地顺序执行ping。通过让多个线程并行运行以执行ping操作来提高性能,就像在此示例代码中一样。

private async void button1_Click(object sender, EventArgs e)
{
    // Make a list of host names to ping
    List<string> hostnames = new List<string>();

    // Use local hostnames a .. z. 
    // and domain names a.com .. z.com
    for(char c = 'a'; c <= 'z'; c++)
    {
        hostnames.Add(c.ToString());
        hostnames.Add("www." + c + ".com");
    }

    // Use some well known hostnames
    hostnames.Add("www.google.com");
    hostnames.Add("www.microsoft.com");
    hostnames.Add("www.apple.com");

    // Ping the hostnames and get the results as a dictionary
    IReadOnlyDictionary<string, bool> results = await Task.Run(() => PingHosts(hostnames));

    // Output the content of the results, note that the order 
    // is not the same as in the original list of
    // hostnames because of parallel processing
    foreach(var result in results)
    {
        if(result.Value)
        {
            textBox1.AppendText("Ping to " + result.Key + ": OK" + Environment.NewLine);
        }
        else
        {
            textBox1.AppendText("Ping to " + result.Key + ": ERROR" + Environment.NewLine);
        }
    }
}

// This function will ping a single host and return true or false
// based on whether it can be pinged
private bool PingSingleHost(string hostname)
{
    try
    {
        Ping ping = new Ping();
        var reply = ping.Send(hostname, 1000);
        bool wasSuccessful = reply.Status == IPStatus.Success;
        return wasSuccessful;
    }
    catch(Exception)
    {
        return false;
    }
}

// Ping the given list of hostnames and return their status
// (can they be pinged) as a dictionary where the Key is the hostname
// and the value is a boolean with the ping result
private IReadOnlyDictionary<string, bool> PingHosts(IEnumerable<string> hostnames)
{
    // Use 30 parallel worker threads
    // This number can be quite high because the
    // workers will spend most time waiting 
    // for an answer
    int numberOfWorkers = 30;

    // Place the hosts into a queue
    ConcurrentQueue<string> jobsQueue = new ConcurrentQueue<string>(hostnames);

    // Use a concurrent dictionary to store the results
    // The concurrent dictionary will automatically handle
    // multiple threads accessing the dictionary at the same time
    ConcurrentDictionary<string, bool> results = new ConcurrentDictionary<string, bool>();

    // Worker function which keeps reading new hostnames from the given jobsQueue
    // and pings those hostnames and writes the result to the given results dictionary
    // until the queue is empty
    ThreadStart Worker = () =>
    {
        string hostname;

        // While the job queue is not empty, get a host from the queue
        while(jobsQueue.TryDequeue(out hostname))
        {
            // Ping the host and 
            bool wasSuccessful = PingSingleHost(hostname);

            // write the result to results dictionary
            results.TryAdd(hostname, wasSuccessful);
        }
    };


    // Start the Worker threads
    List<Thread> workers = new List<Thread>();

    for(int i = 0; i < numberOfWorkers; i++)
    {
        Thread thread = new Thread(Worker);
        thread.Start();
        workers.Add(thread);
    }

    // Wait for all workers to have finished
    foreach(var thread in workers)
    {
        thread.Join();
    }

    return results;
}