C#多IP Ping:如何独立即时获取各IP的Ping回复结果?
多IP Ping结果即时展示的解决方案
问题分析
你当前的代码使用Task.WhenAll等待所有Ping任务完成后统一返回结果,这会导致在线IP的正常回复被离线IP的超时任务阻塞——必须等最慢的任务(比如超时的IP)完成后,所有结果才会一起展示,无法做到即时输出。
核心解决方案
不要等待所有任务批量完成,而是让每个Ping任务完成后立即处理对应的结果。以下两种实现方式都可以达到目标:
方式一:实时处理完成的任务(支持按完成顺序输出)
这种方式通过Task.WhenAny循环等待任意任务完成,处理后移除该任务,直到所有任务结束。优点是可以优先展示先完成的Ping结果,完全不受慢任务影响。
private async ValueTask PingMachine() { var timesToPing = 4; var counter = 1; while (counter <= timesToPing) { await ProcessPingsAsync(counter); counter++; } } private async Task ProcessPingsAsync(int pingRound) { // 收集所有合法IP(如果是多IP集合,这里改为遍历添加) var addresses = new List<string>(); if (Check_IP_Correct(TagService.IP_PLC_List)) { addresses.Add(TagService.IP_PLC_List); } // 预先启动所有Ping任务,存入列表 var pingTasks = addresses.Select(ip => new Ping().SendPingAsync(ip, 1000)) .ToList(); // 循环处理每个完成的任务 while (pingTasks.Any()) { var completedTask = await Task.WhenAny(pingTasks); pingTasks.Remove(completedTask); // 立即处理该任务的结果 var reply = await completedTask; TagService.log_PLC.AppendLine($"Pinged {reply.Address} {pingRound} times | 耗时: {reply.RoundtripTime}ms | 状态: {reply.Status}"); } }
方式二:任务内直接处理结果(代码更简洁)
直接在每个Ping任务的异步流程中完成日志记录,启动所有任务后只需等待全部完成即可(日志已经实时输出)。
private async ValueTask PingMachine() { var timesToPing = 4; var counter = 1; while (counter <= timesToPing) { await ProcessPingsAsync(counter); counter++; } } private async Task ProcessPingsAsync(int pingRound) { var addresses = new List<string>(); if (Check_IP_Correct(TagService.IP_PLC_List)) { addresses.Add(TagService.IP_PLC_List); } // 为每个IP启动Ping任务,完成后立即写日志 var tasks = addresses.Select(async ip => { var reply = await new Ping().SendPingAsync(ip, 1000); TagService.log_PLC.AppendLine($"Pinged {ip} {pingRound} times | 耗时: {reply.RoundtripTime}ms | 状态: {reply.Status}"); }); // 等待所有任务执行完毕(日志已实时输出) await Task.WhenAll(tasks); }
额外说明
如果TagService.IP_PLC_List是多IP集合(而非单个IP),需要调整地址收集逻辑,确保所有合法IP都被加入Ping任务:
// 替换原地址收集代码 var addresses = TagService.IP_PLC_List.Where(ip => Check_IP_Correct(ip)).ToList();
内容的提问来源于stack exchange,提问作者Mdarende
相关产品推荐
相关产品推荐

