c# - Ping.SendAsync 陷入无限循环
问题描述
我正在尝试获取本地网络上所有主机的列表。按照这个 Stackoverflow 线程。但是 Ping.SendAsync() 卡在无限循环中,即使我保持很小的超时时间,即 20。这是我的代码。
static CountdownEvent countdown;
static int upCount = 0;
static object lockObj = new object();
const bool resolveNames = false;
static List<string> activeInterfaces = new List<string>();
static void p_PingCompleted(object sender, PingCompletedEventArgs e)
{
try
{
string ip = (string)e.UserState;
if (e.Reply != null && e.Reply.Status == IPStatus.Success)
{
//if (resolveNames)
//{
// string name;
// try
// {
// IPHostEntry hostEntry = Dns.GetHostEntry(ip);
// name = hostEntry.HostName;
// }
// catch (SocketException ex)
// {
// name = "?";
// }
// Console.WriteLine("{0} ({1}) is up: ({2} ms)", ip, name, e.Reply.RoundtripTime);
//}
//else
//{
activeInterfaces.Add(ip);
Console.WriteLine("{0} is up: ({1} ms)", ip, e.Reply.RoundtripTime);
//}
lock (lockObj)
{
upCount++;
}
}
else if (e.Reply == null)
{
Console.WriteLine("Pinging {0} failed. (Null Reply object?)", ip);
}
countdown.Signal();
}
catch (Exception exp)
{
Console.WriteLine("Here you go...");
}
}
[HttpGet]
[Route("api/pc/getOnlinePCs")]
public List<string> GetOnlinePCs()
{
activeInterfaces.Clear();
//List<string> activeInterfaces=new List<string>();
string ipBase = "";
var host = Dns.GetHostEntry(Dns.GetHostName());
foreach (var ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
ipBase = ip.ToString().Substring(0, (ip.ToString().LastIndexOf(".") + 1));//"10.22.4.";
}
}
countdown = new CountdownEvent(1);
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 2; i < 254; i++)
{
string ip = ipBase + i.ToString();
//var tcpClient = new TcpClient();
//tcpClient.Connected += new PingCompletedEventHandler(p_PingCompleted);
Ping ping = new Ping();
ping.PingCompleted += new PingCompletedEventHandler(p_PingCompleted);
countdown.AddCount();
ping.SendAsync(ip, 20, ip);
}
countdown.Signal();
countdown.Wait();
sw.Stop();
TimeSpan span = new TimeSpan(sw.ElapsedTicks);
Console.WriteLine("Took {0} milliseconds. {1} hosts active.", sw.ElapsedMilliseconds, upCount);
Console.ReadLine();
return activeInterfaces;
}
我不认为 SO 线程中提供的解决方案已过期,而是我会犯一个小的逻辑错误,因为我是前端人员。谢谢!
编辑
根据专家评论,我将 SendAsync 代码包装在 try/catch 中,最后阻塞为
try
{
Ping ping = new Ping();
ping.PingCompleted += new PingCompletedEventHandler(p_PingCompleted);
countdown.AddCount();
ping.SendAsync(ip, 20, ip);
}
catch(Exception exception)
{
Console.WriteLine($"Exception on {ip} .Technical details: {exception}");
}
finally
{
countdown.AddCount();
}
但是当我调试代码时,它总是落入 finally 块。不要异常阻塞,在 253 ping 迭代完成后,再次无限循环!@Evk 和 @jdweng 请帮忙!
解决方案
Ping SendAsync 没有按照您的预期进行,您可以释放资源,但是您需要自己处理从另一个线程返回的答案,您需要挂钩 PingCompleted 来处理答案。
你最好通过调用 ping 和在你的方法中为你的方法创建一个异步方法,并通过自己实现它在异步方法中调用你的方法 https://docs.microsoft.com/en-us/dotnet/standard/parallel-任务中的编程/如何包装 eap 模式
Ping pingSender = new Ping ();
// When the PingCompleted event is raised,
// the PingCompletedCallback method is called.
pingSender.PingCompleted += new PingCompletedEventHandler (PingCompletedCallback);
// Create a buffer of 32 bytes of data to be transmitted.
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte [] buffer = Encoding.ASCII.GetBytes (data);
// Wait 12 seconds for a reply.
int timeout = 12000;
// Set options for transmission:
// The data can go through 64 gateways or routers
// before it is destroyed, and the data packet
// cannot be fragmented.
PingOptions options = new PingOptions (64, true);
// Send the ping asynchronously.
// Use the waiter as the user token.
// When the callback completes, it can wake up this thread.
pingSender.SendAsync (who, timeout, buffer, options, waiter);
// Prevent this example application from ending.
// A real application should do something useful
// when possible.
waiter.WaitOne ();
推荐阅读
- java - 无法连接到 oracle 数据库。它说“无法从数据源确定 jdbc url”
- laravel - 尝试在 GetStream 中向用户添加提要时出错
- java - java.lang.OutOfMemoryError 的含义:null
- go - 如何在 GO 中访问另一个文件
- android - 我收到此错误“任务':app:compileDebugJavaWithJavac'的执行失败。”
- java - Java android 改变亮度 Android 6.0
- visual-studio-code - VSCode 的默认设置文件在什么位置?
- ios - 将从 Json 接收的数据存储在数组中,并在 Swift 4 中的 tableView 中显示结果
- performance - Jmeter - 获取网站的准确可访问时间
- arrays - 如何在 ionic 3 中向数组添加或推送值