You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#使用Ping异步实现网络设备发现时如何等待所有线程结束

解决方案

方案1:使用CountdownEvent计数等待(适配你当前的EAP异步实现,无需大改原有逻辑)

核心逻辑

你发起N个Ping请求就初始化CountdownEvent的初始计数为N,每完成一个Ping请求就将计数减1,主线程阻塞等待计数归0,即代表所有异步请求全部处理完成。
同时需要补充ipList的并发锁,避免多线程写入导致的数据错乱/丢失。

修改步骤

  1. 新增静态成员:
// 原有静态列表
private static List<string> ipList = new List<string>();
// 计数同步对象
private static CountdownEvent _pingCountdown;
// 列表写入锁
private static object _listLock = new object();
  1. 修改Main方法逻辑:
static void Main(string[] args)
{
    // 执行逻辑获取子网掩码和本地地址,先计算出需要Ping的IP总数量,替换为你实际的数值
    int totalPingCount = 254;
    _pingCountdown = new CountdownEvent(totalPingCount);

    // 用for循环递增IP地址
    for (int i = 1; i <= totalPingCount; i++) 
    {
        IPAddress ip_address = ...; // 替换为你生成IP的原有逻辑
        PingAsync(ip_address);
    }

    // 等待所有Ping请求完成,代替原来的手动ReadLine
    _pingCountdown.Wait();
    // 用完释放资源
    _pingCountdown.Dispose();

    Console.WriteLine("List of all devices found :\n");
    ipList.ForEach(str =>
    {
        Console.WriteLine($"\t=> {str}");
    });
    Console.ReadLine();
}
  1. 修改PingCompletedCallback的完成逻辑,补充计数减1和列表锁:
private static void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
    try
    {
        if (e.Cancelled || e.Error != null)
        {
            Console.WriteLine("Ping failed !");
            if(e.Error != null) Console.WriteLine(e.Error.ToString());
            return;
        }

        PingReply reply = e.Reply;
        if(reply.Status == IPStatus.Success)
        {
            // 加锁保证线程安全
            lock(_listLock)
            {
                ipList.Add(reply.Address.ToString());
            }
        }
    }
    finally
    {
        // 无论成功失败,都触发计数减1
        _pingCountdown.Signal();
        ((AutoResetEvent)e.UserState)?.Dispose();
        ((Ping)sender).Dispose();
    }
}

方案2:改用TAP异步模式(更简洁的现代写法)

如果允许调整PingAsync的实现,可以直接用Ping类自带的SendPingAsync方法,返回Task对象,直接用Task.WhenAll等待所有任务完成:

static async Task Main(string[] args)
{
    List<Task<PingReply>> pingTasks = new List<Task<PingReply>>();
    List<string> ipList = new List<string>();
    // 替换为你生成的所有待Ping IP列表
    List<IPAddress> allIps = ...;
    string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    byte[] buffer = Encoding.ASCII.GetBytes(data);
    int timeout = 1200;
    PingOptions options = new PingOptions(64, true);

    foreach (var ip in allIps)
    {
        pingTasks.Add(new Ping().SendPingAsync(ip, timeout, buffer, options));
    }

    // 等待所有Ping完成
    var results = await Task.WhenAll(pingTasks);
    foreach (var res in results)
    {
        if(res.Status == IPStatus.Success)
        {
            ipList.Add(res.Address.ToString());
        }
    }

    // 打印列表
    Console.WriteLine("List of all devices found :\n");
    ipList.ForEach(str => Console.WriteLine($"\t=> {str}"));
    Console.ReadLine();
}

额外注意点

  • 你原有代码里PingCompletedCallback中实例化Program prog = new Program();是冗余代码,没有用到可以直接删掉
  • 所有Ping和同步对象用完要主动释放,避免内存泄漏

内容的提问来源于stack exchange,提问作者FrougeurPro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 15:27:02