我构建了一个简单的程序,它包含一个包含一组服务器主机名的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++;
}
}
答案 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;
}