真心急求! C#程序,超大数据量,超高并发任务,应该如何处理?

Nc01 2013-11-06 12:31:02
用C#写一个程序,运行在一台10G内存的服务器上,
作用是24小时不停的 ping 10万个ip,以获取每个ip的主机是否正常连接,
每隔2秒钟这10万个ip就全部ping一次,
并记录返回的指定信息,部分信息需要存储在硬盘或者数据库上.
与此同时,返回的信息需要一些运算和加工,展现给使用者.


如果ip只有少量几个,而且不是不停的运行,那我可以轻松实现,
但是大量的数据和高并发性出现后,C#的程序是不是应该大换血了?
究竟应该如何处理代码?如何做这个程序?


...全文
11102 56 打赏 收藏 转发到动态 举报
写回复
用AI写文章
56 条回复
切换为时间正序
请发表友善的回复…
发表回复
mjp1234airen4385 2013-11-12
  • 打赏
  • 举报
回复
拿个板凳去。
showjim 2013-11-11
  • 打赏
  • 举报
回复
补充说明:降低并发数量,可以降低CPU占用率,所以可以根据实际情况选择并发数量。
引用 50 楼 u012737501 的回复:
哥们你费了不少心思,多谢多谢! 我现在这样做,我把1万个IP分成10组,每组对应一个线程,每个线程里边用异步Ping.SendAsync()的方法进行ping;因为要对ping后的结果做些处理,所以异步完成处理事件里要调用一个方法Summary(),但是每次测试都在这个方法里报错.. 是不是既用了异步又用多线程,是会发生冲突? 还有我想问下你测试的结果,如果能做到10万个ip两秒一次不停的ping, 7x24不间断运行,需要什么样的硬件配置和程序优化?你直接说个大概结论. 再次感谢各位的关注.
1、异步不需要自己new线程,使用的是系统线程池,关键是不要做多余的事,否则会对其它任务产生影响。 2、我想Summary至少需要操作一个共享队列(最好是仅仅操作一下共享队列,不要阻塞线程池中的线程,数据处理的事应该交给其它线程同步处理),需要lock操作。 3、根据我的测试结果推论,需要2MB/s的上行带宽、3MB/s的下行带宽、8核心的CPU。至于7x24不间断一般都是受实际网络环境影响的。硬件方面可能需要一台备用机器,程序优化要根据你的其他实际业务需求而定。
showjim 2013-11-11
  • 打赏
  • 举报
回复
引用 52 楼 sbwwkmyd 的回复:
1、异步不需要自己new线程,使用的是系统线程池,关键是不要做多余的事,否则会对其它任务产生影响。 2、我想Summary至少需要操作一个共享队列(最好是仅仅操作一下共享队列,不要阻塞线程池中的线程,数据处理的事应该交给其它线程同步处理),需要lock操作。 3、根据我的测试结果推论,需要2MB/s的上行带宽、3MB/s的下行带宽、8核心的CPU。至于7x24不间断一般都是受实际网络环境影响的。硬件方面可能需要一台备用机器,程序优化要根据你的其他实际业务需求而定。
有一点比较重要的是,IP要正常。由于我采集的IP地址都是一些主站IP,所以很少有失效的,可以肯定的是在测试的时候,前10000个只有一个不正常。 如果IP质量不行,2秒就不能强求了。N个并发处理量基本相当于2*N秒单线程的处理量。 所以如果超时IP数量超过并发数,循环周期就肯定超过2秒。 最糟糕的情况是所有IP都不正常,这时候的循环周期时间接近于 IP数量*超时单位/并发数。
showjim 2013-11-11
  • 打赏
  • 举报
回复
引用 40 楼 sbwwkmyd 的回复:
白费了一天时间采集了10W主站IP,结果一点用没有。 关于PING的测试结果非常糟糕。以2秒为一次循环,超时设置为2秒,最大PING实例数量为512,IP数量为2^n。下面是本地测试结果: IP数量 <= 8 ,完全正常。 16 <= IP数量 <= 32 ,第一次循环正常,从第二次循环开始每轮1个IP失败。 64 <= IP数量 <= 256 ,第一次循环正常,从第二次循环开始每轮10%左右IP失败。 IP数量 = 512 ,第一次循环正常,从第二次循环开始每轮20%左右IP失败。成功 > 200IP/s,测试中的单位时间成功IP最多的情况。 IP数量 = 1024 ,第一次循环50%左右IP失败,从第二次循环开始每轮70%左右IP失败,而且由于超时太多循环周期在3-4s左右。成功 < 100IP/s。 IP数量 = 2048 ,每轮循环75%以上IP失败,循环周期在8s左右,到这里为止最大网络流量不到30KB/s。成功 < 64IP/s。 继续测试,结果会越来越糟糕。接下来不管成功率如果,测试一个“高并发”的情况。 PING实例 = 1024 ,10KB/s <= 网络流量 60KB/s,10% <= CPU <= 30%。 PING实例 = 2048 ,20KB/s <= 网络流量 100KB/s,15% <= CPU <= 50%。 PING实例 = 4096 ,40KB/s <= 网络流量 100KB/s,CPU = 100%。 好了,我这台烂机器没法再测试下去了。由于10W IP空转(仅仅不执行PING操作)测试CPU最多2%,可见PING是非常消耗CPU的操作。 现在有一点可以确定,我本地环境PING的并发量与网络带宽关系不大。至于是不是网络环境(路由节点)的限制,无法确定,但是很可能现实环境无法实现高并发。
今天使用Socket.ReceiveFromAsync写了一个PING,结果与System.Net.NetworkInformation.Ping的测试结果在成功率方面相当接近。 因为Socket.ReceiveFromAsync会丢包,也许System.Net.NetworkInformation.Ping也是这个原因。
Nc01 2013-11-11
  • 打赏
  • 举报
回复
引用 41 楼 sbwwkmyd 的回复:
基于以上测试,我认为只要带宽达到2MB/s,6个CPU核心就差不多可以达到楼主需求了
如果真的仅仅是这样,我们公司能解决. 还有没有其他需要考虑的硬件和网络关键点?
Nc01 2013-11-11
  • 打赏
  • 举报
回复
引用 48 楼 sbwwkmyd 的回复:
另外在最大超时段内,PING标识仅仅使用进程ID并且并发超过65536的话,可能会出现标识冲突。
哥们你费了不少心思,多谢多谢! 我现在这样做,我把1万个IP分成10组,每组对应一个线程,每个线程里边用异步Ping.SendAsync()的方法进行ping;因为要对ping后的结果做些处理,所以异步完成处理事件里要调用一个方法Summary(),但是每次测试都在这个方法里报错.. 是不是既用了异步又用多线程,是会发生冲突? 还有我想问下你测试的结果,如果能做到10万个ip两秒一次不停的ping, 7x24不间断运行,需要什么样的硬件配置和程序优化?你直接说个大概结论. 再次感谢各位的关注.
showjim 2013-11-10
  • 打赏
  • 举报
回复
引用 48 楼 sbwwkmyd 的回复:
另外在最大超时段内,PING标识仅仅使用进程ID并且并发超过65536的话,可能会出现标识冲突。
另外在最大超时段内,PING标识仅仅使用进程ID并且并发超过65536的话,可能会出现ICMP序列号冲突。
showjim 2013-11-10
  • 打赏
  • 举报
回复
引用 46 楼 caozhy 的回复:
你达到每秒5万次了么?
另外在最大超时段内,PING标识仅仅使用进程ID并且并发超过65536的话,可能会出现标识冲突。
showjim 2013-11-10
  • 打赏
  • 举报
回复
引用 46 楼 caozhy 的回复:
你达到每秒5万次了么?
测试中我的带宽只能撑到1W左右,我的古董CPU最多可能就能2W,没办法继续测试了。
threenewbee 2013-11-10
  • 打赏
  • 举报
回复
引用 45 楼 sbwwkmyd 的回复:
可以说测试了一上午,至少现在还没有被封网络。
你达到每秒5万次了么?
showjim 2013-11-10
  • 打赏
  • 举报
回复
可以说测试了一上午,至少现在还没有被封网络。
showjim 2013-11-10
  • 打赏
  • 举报
回复
引用 41 楼 sbwwkmyd 的回复:
当然可以肯定这个CPU的消耗是System.Net.NetworkInformation.Ping或者windows操作系统的处理造成的(可能与异步有关,我没有测试同步的情况)。 如果要解决这个问题,需要自己使用rawSocket发ICMP包,并且管理他们。
为了进一步搞清楚原因,我自己写了一个PING。不管采用同步还是异步方式,并发达到2048都会造成CPU 100%。现在基本可以确定是操作系统造成的,很可能是对于没有端口号的接收数据的Socket查找使用了O(n)的线性算法,所以并发时间复杂度为O(n^2)。
引用 42 楼 sbwwkmyd 的回复:
但是要实现楼主的需求,关键是每秒的成功IP数。我想当然的认为,这个应该不是操作系统的问题,应该是网络环境(路由节点)缺少路由缓存造成的。
新的测试结果表明,失败率高也是由System.Net.NetworkInformation.Ping或者windows操作系统造成的。至于为什么会这样,还不清楚。 测试还是以2秒为一次循环,超时设置为2秒,最大PING实例数量为256(本地测试中比较稳定的最大并发数,也许128能更稳定),IP数量为2^n。下面是本地测试结果: IP数量 <= 8192 ,完全正常,循环周期 < 1s。100KB/s <= 网络流量 300KB/s,CPU <= 50%。 IP数量 = 16384 ,基本正常,1s < 循环周期 < 2s。200KB/s <= 网络流量 600KB/s,70% <= CPU <= 90%。 我本地的带宽是4Mb/s = 512KB/s (上面的600KB/s是任务管理器中的6%),测试只能到这里了。有一点要注意,超时或者出错对于CPU占用率的增大影响严重。 基于以上测试,我认为只要带宽达到2MB/s,6个CPU核心就差不多可以达到楼主需求了(我的CPU是单核心Inter Celeron M CPU 520 1.6GHz)。当然重要的是,PING的失败率不能太高,否则4个CPU承受不了,而且循环周期会被延长。 下面是基于fastCSharp的测试程序,由于原来是异步操作,后来改为同步只是简单修改了一下,所以并不逻辑有些怪异。
        sealed class pingInterval : IDisposable
        {
            private sealed class pinger : IDisposable
            {
                private readonly pingInterval pingInterval;
                private fastCSharp.net.ping ping;
                private System.Net.IPEndPoint ip;
                public pinger(pingInterval pingInterval)
                {
                    this.pingInterval = pingInterval;
                    ping = new fastCSharp.net.ping(1000, pingInterval.timeoutMilliseconds, null);
                }
                internal void Next()
                {
                    fastCSharp.threading.task.TinyTask.Add(next);
                }
                private void next()
                {
                    for (ip = pingInterval.getIP(); ip != null; ip = pingInterval.getIP()) pingInterval.onCompleted(ip, ping.Ping(ip));
                    pingInterval.free(this);
                }
                public void Dispose()
                {
                    fastCSharp.net.ping ping = this.ping;
                    this.ping = null;
                    if (ping != null) ping.Dispose();
                }
            }
            private const int maxPingCount = 256;
            private readonly System.Net.IPEndPoint[] ips;
            private int ipIndex;
            private readonly object ipLock = new object();
            private readonly int intervalSeconds;
            private readonly int timeoutMilliseconds;
            private action<System.Net.IPEndPoint, bool> onCompleted;
            private pinger[] pings;
            private readonly pinger[] freePings;
            private readonly pinger[] nextPings;
            private int freePingIndex;
            private DateTime pingTime;
            private readonly System.Timers.Timer timer;
            private readonly object pingLock = new object();
            public pingInterval(System.Net.IPEndPoint[] ips, int intervalSeconds, int timeoutMilliseconds, action<System.Net.IPEndPoint, bool> onCompleted)
            {
                this.ips = ips;
                this.intervalSeconds = intervalSeconds;
                this.timeoutMilliseconds = timeoutMilliseconds;
                this.onCompleted = onCompleted;
                freePingIndex = (intervalSeconds * 1000) / (timeoutMilliseconds + 1000);
                if (freePingIndex <= 1) freePingIndex = ips.Length;
                else freePingIndex = ips.Length / freePingIndex + 1;
                if (freePingIndex > maxPingCount) freePingIndex = maxPingCount;
                pings = new pinger[freePingIndex];
                freePings = new pinger[freePingIndex];
                nextPings = new pinger[freePingIndex]; 
                for (int index = freePingIndex; index != 0; pings[index] = freePings[index] = new pinger(this)) --index;
                timer = new System.Timers.Timer(intervalSeconds * 1000);
                timer.AutoReset = false;
                timer.Elapsed += next;
                pingTime = DateTime.Now;
                next(null, null);
            }
            private void next(object sender, System.Timers.ElapsedEventArgs e)
            {
                while (wait())
                {
                    Console.WriteLine("Start " + DateTime.Now.toString());
                    System.Threading.Monitor.Enter(pingLock);
                    int count = freePingIndex;
                    try
                    {
                        Array.Copy(freePings, nextPings, freePingIndex);
                        freePingIndex = 0;
                    }
                    finally { System.Threading.Monitor.Exit(pingLock); }
                    while (count != 0) nextPings[--count].Next();
                    DateTime now = DateTime.Now;
                    if ((pingTime = pingTime.AddSeconds(this.intervalSeconds)) > now)
                    {
                        timer.Interval = (pingTime - now).TotalMilliseconds;
                        if (pings != null) timer.Start();
                        break;
                    }
                }
            }
            private bool wait()
            {
                System.Threading.Monitor.Enter(ipLock);
                try
                {
                    if (pings != null)
                    {
                        if (ipIndex != 0) System.Threading.Monitor.Wait(ipLock);
                        ipIndex = ips.Length;
                        return true;
                    }
                }
                finally { System.Threading.Monitor.Exit(ipLock); }
                return false;
            }
            private System.Net.IPEndPoint getIP()
            {
                System.Threading.Monitor.Enter(ipLock);
                try
                {
                    if (ipIndex != 0)
                    {
                        System.Net.IPEndPoint ip = ips[--ipIndex];
                        if (ipIndex == 0) System.Threading.Monitor.Pulse(ipLock);
                        return ip;
                    }
                }
                finally { System.Threading.Monitor.Exit(ipLock); }
                return null;
            }
            private void free(pinger ping)
            {
                System.Threading.Monitor.Enter(pingLock);
                try
                {
                    freePings[freePingIndex++] = ping;
                }
                finally { System.Threading.Monitor.Exit(pingLock); }
            }
            public void Dispose()
            {
                System.Threading.Monitor.Enter(ipLock);
                try
                {
                    if (pings != null)
                    {
                        timer.Stop();
                        timer.Elapsed -= next;
                        foreach (pinger ping in pings) ping.Dispose();
                        pings = null;
                    }
                    System.Threading.Monitor.Pulse(ipLock);
                }
                finally { System.Threading.Monitor.Exit(ipLock); }
            }
        }
        static int pingCount;
        static int pingErrorCount;
        static int loopCount = -1;
        static System.Net.IPEndPoint[] ips;
        static int ipCount;
        static void onPing(System.Net.IPEndPoint ip, bool isPing)
        {
            if (System.Threading.Interlocked.Decrement(ref ipCount) == -1)
            {
                System.Threading.Interlocked.Add(ref ipCount, ips.Length);
                if (++loopCount != 0) Console.WriteLine(DateTime.Now.toString() + " LOOP[" + loopCount.toString() + "] Count[" + (pingCount / loopCount).toString() + "] ErrorCount[" + pingErrorCount.toString() + "]");
            }
            if (isPing) ++pingCount;
            else ++pingErrorCount;
            //Console.WriteLine(DateTime.Now.ToString("HH:mm:ss") + " " + ip.ToString() + " : " + (reply != null && reply.Status == System.Net.NetworkInformation.IPStatus.Success).ToString());
        }
        static void Main(string[] args)
        {
            ips = System.IO.File.ReadAllText(@"d:\ip.txt").Split(',').left(16384).getArray(value => new System.Net.IPEndPoint(System.Net.IPAddress.Parse(value), 0));
            using (pingInterval pingInterval = new pingInterval(ips, 2, 2000, onPing))
            {
                Console.ReadKey();
            }
            Console.WriteLine("End");

            Console.ReadKey();
        }
showjim 2013-11-09
  • 打赏
  • 举报
回复
但是要实现楼主的需求,关键是每秒的成功IP数。我想当然的认为,这个应该不是操作系统的问题,应该是网络环境(路由节点)缺少路由缓存造成的。
showjim 2013-11-09
  • 打赏
  • 举报
回复
引用 40 楼 sbwwkmyd 的回复:
由于10W IP空转(仅仅不执行PING操作)测试CPU最多2%,可见PING是非常消耗CPU的操作。
当然可以肯定这个CPU的消耗是System.Net.NetworkInformation.Ping或者windows操作系统的处理造成的(可能与异步有关,我没有测试同步的情况)。 如果要解决这个问题,需要自己使用rawSocket发ICMP包,并且管理他们。
showjim 2013-11-09
  • 打赏
  • 举报
回复
白费了一天时间采集了10W主站IP,结果一点用没有。 关于PING的测试结果非常糟糕。以2秒为一次循环,超时设置为2秒,最大PING实例数量为512,IP数量为2^n。下面是本地测试结果: IP数量 <= 8 ,完全正常。 16 <= IP数量 <= 32 ,第一次循环正常,从第二次循环开始每轮1个IP失败。 64 <= IP数量 <= 256 ,第一次循环正常,从第二次循环开始每轮10%左右IP失败。 IP数量 = 512 ,第一次循环正常,从第二次循环开始每轮20%左右IP失败。成功 > 200IP/s,测试中的单位时间成功IP最多的情况。 IP数量 = 1024 ,第一次循环50%左右IP失败,从第二次循环开始每轮70%左右IP失败,而且由于超时太多循环周期在3-4s左右。成功 < 100IP/s。 IP数量 = 2048 ,每轮循环75%以上IP失败,循环周期在8s左右,到这里为止最大网络流量不到30KB/s。成功 < 64IP/s。 继续测试,结果会越来越糟糕。接下来不管成功率如果,测试一个“高并发”的情况。 PING实例 = 1024 ,10KB/s <= 网络流量 60KB/s,10% <= CPU <= 30%。 PING实例 = 2048 ,20KB/s <= 网络流量 100KB/s,15% <= CPU <= 50%。 PING实例 = 4096 ,40KB/s <= 网络流量 100KB/s,CPU = 100%。 好了,我这台烂机器没法再测试下去了。由于10W IP空转(仅仅不执行PING操作)测试CPU最多2%,可见PING是非常消耗CPU的操作。 现在有一点可以确定,我本地环境PING的并发量与网络带宽关系不大。至于是不是网络环境(路由节点)的限制,无法确定,但是很可能现实环境无法实现高并发。
  • 打赏
  • 举报
回复
你还是吧心思放在100而不是10万上吧! 过分与不及,其实都是一样的。我不会因为有人吹牛就上当。
showjim 2013-11-08
  • 打赏
  • 举报
回复
引用 13 楼 yuwenge 的回复:
你就想什么网卡能支持每秒10w次的并发访问吧。 你的程序能写出来,你的硬件支持得了么?
并不是说的IP,说的是访问次数/s。
卧_槽 2013-11-08
  • 打赏
  • 举报
回复
引用 36 楼 sbwwkmyd 的回复:
[quote=引用 35 楼 yuwenge 的回复:]你的网络服务商不封你的ip么?
局域网测试。 至于ISP会如何处理,还真不知道,不过我现在倒是有想法试一试。[/quote] 靠,好霸道的局域网,10w个ip。
weizhuangwen 2013-11-07
  • 打赏
  • 举报
回复
楼主的上层老板是要干坏事呀~~没有这样的需求的,一看就知道要搞某些事情。没有哪家公司有属于自己的10W台服务器,那么这些服务器肯定是分散式的,而且10W台也不处于一个地区,肯定遍布全球各地。从你的每两秒PING一次,可以看出在对全球各地的服务器进行监视,而且实时性需求要很高(精确到2秒)。综合分析:“这些服务器----肉鸡”
showjim 2013-11-07
  • 打赏
  • 举报
回复
修改了一个关于Timer的BUG,增加了PING超时参数。
        sealed class pingInterval : IDisposable
        {
            private sealed class pinger : IDisposable
            {
                private readonly pingInterval pingInterval;
                private System.Net.NetworkInformation.Ping ping;
                private System.Net.IPAddress ip;
                public pinger(pingInterval pingInterval)
                {
                    this.pingInterval = pingInterval;
                    ping = new System.Net.NetworkInformation.Ping();
                    ping.PingCompleted += pingCompleted;
                }
                internal void Next()
                {
                    while (ping != null)
                    {
                        if ((ip = pingInterval.getIP()) == null)
                        {
                            pingInterval.free(this);
                            break;
                        }
                        else
                        {
                            try
                            {
                                ping.SendAsync(ip, pingInterval.timeoutMilliseconds, this);
                                break;
                            }
                            catch { pingInterval.onCompleted(ip, false); }
                        }
                    }
                }
                private void pingCompleted(object sender, System.Net.NetworkInformation.PingCompletedEventArgs e)
                {
                    pingInterval.onCompleted(ip, e.Error == null);
                    Next();
                }
                public void Dispose()
                {
                    if (ping != null)
                    {
                        ping.PingCompleted -= pingCompleted;
                        ping.Dispose();
                        ping = null;
                    }
                }
            }
            private const int maxPingCount = 1 << 15;
            private readonly System.Net.IPAddress[] ips;
            private int ipIndex;
            private readonly object ipLock = new object();
            private readonly int intervalSeconds;
            private readonly int timeoutMilliseconds;
            private action<System.Net.IPAddress, bool> onCompleted;
            private pinger[] pings;
            private readonly pinger[] freePings;
            private readonly pinger[] nextPings;
            private int freePingIndex;
            private DateTime pingTime;
            private readonly System.Timers.Timer timer;
            private readonly object pingLock = new object();
            public pingInterval(System.Net.IPAddress[] ips, int intervalSeconds, int timeoutMilliseconds, action<System.Net.IPAddress, bool> onCompleted)
            {
                this.ips = ips;
                this.intervalSeconds = intervalSeconds;
                this.timeoutMilliseconds = timeoutMilliseconds;
                this.onCompleted = onCompleted;
                freePingIndex = (intervalSeconds * 1000) / (timeoutMilliseconds + 100);
                if (freePingIndex <= 1) freePingIndex = ips.Length;
                else freePingIndex = ips.Length / freePingIndex + 1;
                if (freePingIndex > maxPingCount) freePingIndex = maxPingCount;
                pings = new pinger[freePingIndex];
                freePings = new pinger[freePingIndex];
                nextPings = new pinger[freePingIndex]; 
                for (int index = freePingIndex; index != 0; pings[index] = freePings[index] = new pinger(this)) --index;
                timer = new System.Timers.Timer(intervalSeconds * 1000);
                timer.AutoReset = false;
                timer.Elapsed += next;
                pingTime = DateTime.Now;
                next(null, null);
            }
            private void next(object sender, System.Timers.ElapsedEventArgs e)
            {
                while (wait())
                {
                    System.Threading.Monitor.Enter(pingLock);
                    int count = freePingIndex;
                    try
                    {
                        Array.Copy(freePings, nextPings, freePingIndex);
                        freePingIndex = 0;
                    }
                    finally { System.Threading.Monitor.Exit(pingLock); }
                    while (count != 0) nextPings[--count].Next();
                    DateTime now = DateTime.Now;
                    if ((pingTime = pingTime.AddSeconds(this.intervalSeconds)) > now)
                    {
                        timer.Interval = (pingTime - now).TotalMilliseconds;
                        if (pings != null) timer.Start();
                        break;
                    }
                }
            }
            private bool wait()
            {
                System.Threading.Monitor.Enter(ipLock);
                try
                {
                    if (pings != null)
                    {
                        if (ipIndex != 0) System.Threading.Monitor.Wait(ipLock);
                        ipIndex = ips.Length;
                        return true;
                    }
                }
                finally { System.Threading.Monitor.Exit(ipLock); }
                return false;
            }
            private System.Net.IPAddress getIP()
            {
                System.Threading.Monitor.Enter(ipLock);
                try
                {
                    if (ipIndex != 0)
                    {
                        System.Net.IPAddress ip = ips[--ipIndex];
                        if (ipIndex == 0) System.Threading.Monitor.Pulse(ipLock);
                        return ip;
                    }
                }
                finally { System.Threading.Monitor.Exit(ipLock); }
                return null;
            }
            private void free(pinger ping)
            {
                System.Threading.Monitor.Enter(pingLock);
                try
                {
                    freePings[freePingIndex++] = ping;
                }
                finally { System.Threading.Monitor.Exit(pingLock); }
            }
            public void Dispose()
            {
                System.Threading.Monitor.Enter(ipLock);
                try
                {
                    if (pings != null)
                    {
                        timer.Stop();
                        timer.Elapsed -= next;
                        foreach (pinger ping in pings) ping.Dispose();
                        pings = null;
                    }
                    System.Threading.Monitor.Pulse(ipLock);
                }
                finally { System.Threading.Monitor.Exit(ipLock); }
            }
        }
加载更多回复(34)

110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧