先看我的代码        private void commTest()
        {
            using (System.Net.NetworkInformation.Ping ping = new System.Net.NetworkInformation.Ping())
            {
                ping.PingCompleted += ping_PingCompleted;
                ping.SendAsync(_ip, null);     
             }
        }
        private void ping_PingCompleted(object sender, System.Net.NetworkInformation.PingCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                _isConnected = false;
                labelStatus.Text = "连接测试被取消";
                return;
            }
            if (e.Error != null)
            {
                labelStatus.Text = e.Error.Message;
                _isConnected = false;
                return;
            }
            if (e.Reply.Status == System.Net.NetworkInformation.IPStatus.Success)
            {
                labelStatus.Text = "已连接";
                _isConnected = true;
                return;
            }
            else
            {
                labelStatus.Text = "连接错误";
                _isConnected = false;
                return;
            }
        }
这样写的话,在我自己的机器上试了很多次一点问题没有,但是用到客户的机器上ping另外一个机器就会直接进入e.cancelled分支。
请问这是为什么?
后来我在ping.SendAsync(_ip, null);     后面加了一个System.Threading.Thread.Sleep(2000);就没事了。
我觉得就算是超时报警也不应该是cancel啊,它直接报个错都行。ping类

解决方案 »

  1.   

    这种问题你应该先查MSDN,然后再查一下那类的源码实现
      

  2.   

    因为你在自己机器上因为链接的都是本地的,所以程序运行没有延时,所以主程序运行结束后,后台线程也运行结束了,后台线程指的是运行ping_PingCompleted这个方法的线程,所以不会出错,然而你用另一个客户端的时候,因为异步线程不会阻塞主线程的运行,所以在ping_PingCompleted这个方法运行结束之前,主线程已经退出了,导致后台线程也退出,所以会进入Cancel分支的结果,然而你使用Thread.Sleep()操作,就是相当于阻塞了主线程的执行,但是这个过程后台线程(执行ping_PingCompleted这个方法的线程)还在执行,当阻塞时间到的时候,也就完成了ping_PingCompleted这个方法的执行了,所以才不会有问题的,其实你在MSDN Ping的异步使用中也可以找到答案的,你必须在主线程调用AutoResetEvent.WaitOne()来确保请求得到一个回复了。具体你可以参考下面的MSDNPing的使用:
    http://msdn.microsoft.com/zh-cn/library/system.net.networkinformation.ping.aspx
    同时这个例子的疑惑也说明你对多线程的不理解,更多多线程内容可以参考我的博客:
    http://blog.csdn.net/lizhi3186575/article/details/8991281