当前位置: 代码迷 >> C# >> C#WinForm平台怎么多线程同时Ping多个IP地址
  详细解决方案

C#WinForm平台怎么多线程同时Ping多个IP地址

热度:95   发布时间:2016-05-05 03:35:01.0
C#WinForm平台如何多线程同时Ping多个IP地址。
我想实现如下图的效果,同时Ping几个IP,显示每个IP的Ping结果:

我把我的测试结果是显示在datagridview中的,一个IP的Ping信息用一行显示。
我之前测试过只Ping一个IP,没什么问题,但是我加了个for,开启几个线程,没个线程Ping一个IP,就不行了。会报错误,
错误提示是:“System.ArgumentOutOfRangeException”类型的未经处理的异常在 System.Windows.Forms.dll 中发生
其他信息: 索引超出范围。必须为非负值并小于集合大小。我定义的iprecord变量的值变成了3,但是我限定的条件是iprecord是小于IP数组Iptotal的长度的,Iptotal的长度就是3。我的VS有点问题,打不了断点,开不到中断信息,点击中断软件就自动关闭了。就只能把信息贴出来。

public void MethodRandomBytesTrue(string[] IP, string istesttime, string istestcount, string maxbuffer, string internaltime, string icmpcount)
        {
            if (istesttime == "False" && istestcount == "False")
            {
                Thread threadmethod = null;
                for (int iprecord = 0; iprecord < IP.Length; iprecord++)
                {                    
                threadmethod = new Thread(new ThreadStart (delegate
                        {
                            DateTime t1 = DateTime.Now;
                            Ping p = new Ping();
                            PingReply reply;
                            PingOptions options = new PingOptions();
                            options.DontFragment = true;
                            System.Random randomnum = new Random();//定义一个随机数
                            int maxbuffernum = Convert.ToInt32(maxbuffer);//用于产生一个随机字节数                        
                            byte[] buffer;
                            FlagNetTest = true;
                            int successcount = 0;
                            int failcount = 0;
                            int icmptotal = 0;
                            int throwcount = 0;
                            int maxtime = 0;
                            int mintime = 0;
                            int avetime = 0;
                            int time = Convert.ToInt32(internaltime);
                            Thread.Sleep(10);
                            DateTime t2 = DateTime.Now;
                            while (FlagNetTest)
                            {
                                t2 = DateTime.Now;
                                //更新Ping测时间
                                dataGridView1.Invoke((MethodInvoker)delegate
                                {
                                    dataGridView1.Rows[iprecord].Cells[1].Value = ((t2 - t1).TotalSeconds).ToString("0.00") + " 秒";
                                });
                                Thread.Sleep(time);//设置刷新时间.
                                icmptotal++;                                    
                                dataGridView1.Invoke((MethodInvoker)delegate
                                {
                                    dataGridView1.Rows[iprecord].Cells[2].Value = (icmptotal - 1).ToString();
                                    dataGridView1.Rows[iprecord].Cells[7].Value = (100 * (float)(icmptotal - 1) / (t2 - t1).TotalSeconds).ToString("0.00") + " 包/秒";
                                });
                                buffer = new byte[randomnum.Next(0, maxbuffernum)];
                                reply = p.Send(IP[iprecord], 1500, buffer);
                                if (reply.Status == IPStatus.Success)
                                {
                                    successcount++;
                                    this.BeginInvoke(new invokedelegate1(UpdatetxtPingSesults), "\n来自 " + reply.Address + " 的回复:  [ 字节:" + reply.Buffer.Length + "   往返时间:" + reply.RoundtripTime + "ms   TTL(生存时间):" + reply.Options.Ttl + " ]\n");
                                    dataGridView1.Invoke((MethodInvoker)delegate
                                    {
                                        dataGridView1.Rows[iprecord].Cells[3].Value = successcount.ToString();
                                    });
                                }
                                else if (reply.Status == IPStatus.TimedOut)
                                {
                                    this.BeginInvoke(new invokedelegate1(UpdatetxtPingSesults), "\nTimesOut\n");
                                    successcount++;
                                    dataGridView1.Invoke((MethodInvoker)delegate
                                    {
                                        dataGridView1.Rows[iprecord].Cells[3].Value = successcount.ToString();
                                    });
                                }
                                else if (reply.Status == IPStatus.SourceQuench)
                                {
                                    throwcount++;
                                    this.BeginInvoke(new invokedelegate1(UpdatetxtPingSesults), "\n已丢失数据包\n");
                                    dataGridView1.Invoke((MethodInvoker)delegate
                                    {
                                        dataGridView1.Rows[iprecord].Cells[5].Value = throwcount.ToString();
                                        dataGridView1.Rows[iprecord].Cells[6].Value = (100 * (float)throwcount / (icmptotal - 1)).ToString("0.00") + "%";//更新丢包率
                                    });
                                }
                                else
                                {
                                    failcount++;
                                    this.BeginInvoke(new invokedelegate1(UpdatetxtPingSesults), "\n目标计算机无法访问\n");
                                    dataGridView1.Invoke((MethodInvoker)delegate
                                    {
                                        dataGridView1.Rows[iprecord].Cells[4].Value = failcount.ToString();
                                    });
                                }
                                dataGridView1.Invoke((MethodInvoker)delegate
                                {
                                    dataGridView1.Rows[iprecord].Cells[2].Value = icmptotal.ToString();
                                });

                                if (!roundtriptime.Contains(Convert.ToInt32(reply.RoundtripTime)))
                                {
                                    roundtriptime.Add(Convert.ToInt32(reply.RoundtripTime));
                                    Thread.Sleep(10);
                                    maxtime = roundtriptime.Max();
                                    mintime = roundtriptime.Min();
                                    avetime = (int)roundtriptime.Average();
                                    dataGridView1.Invoke((MethodInvoker)delegate
                                    {
                                        dataGridView1.Rows[iprecord].Cells[8].Value = maxtime.ToString() + "/" + mintime.ToString() + "/" + avetime.ToString() + " 毫秒";
                                    });
                                }
                            }
                        }));
                    threadmethod.Start();
                }      
        }

但是我采用
 for (int iprecord = 0; iprecord < IP.Length; iprecord++)
  {   
        MessageBox(iprecord.ToString());
}
看iprecord的值变化,又是正常的。
为何我加上线程后,iprecord就超出限定了。
------解决思路----------------------
当你的线程在运行的时候iprecord不知道变成几了,当然会出错
------解决思路----------------------
你开启的多线程 又使用同一个对象..能不乱么 - - .
------解决思路----------------------
业务逻辑和UI完全混在了一起,不出错才怪。试着把业务逻辑分离出来封装到单独的类里,通过事件通知界面进行变化,相信你的问题自然会被解决的。
------解决思路----------------------
闭包问题
不要用匿名函数

写个线程函数执行
参数全部传入

不要用全局变量
------解决思路----------------------
                for (int iprecord = 0; iprecord < IP.Length; iprecord++)
                {
                           int iprecord2 = iprecord;
                           .................
  相关解决方案