将Ping应用程序转换为多线程版本以提高速度 - C#

时间:2010-01-22 01:10:58

标签: c# multithreading network-programming backgroundworker

我有一个应用程序,它会ping本地子网上的每个可能的IP,以便编译响应的IP地址列表。目前,它一次ping所有255个。是否可以通过一次ping多个线程来转换此应用程序以使用多个线程来提高速度?我是多线程概念的新手,并认为这是一种很好的学习方法(只要当然可能)。

此外,您可以教育我的任何风格改进也会有所帮助。

提前谢谢

以下是backgroundWorker1_DoWork事件中的当前ping方法。

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
            count = 0;
            for (int i = 1; i < 255; i++)
            {
                Ping ping = new Ping();
                PingReply pingreply = ping.Send(IPAddress.Parse(locip[0] + "." + locip[1] + "." + locip[2] + "." + i));
                count += 1;

                if (pingreply.Status == IPStatus.Success)
                {
                    status = "o";
                    repAddress = pingreply.Address.ToString(); ;
                    repRoundtrip = pingreply.RoundtripTime.ToString();
                    repTTL = pingreply.Options.Ttl.ToString();
                    repBuffer = pingreply.Buffer.Length.ToString();
                    string[] lineBuffer = { status, repAddress, repRoundtrip, repTTL, repBuffer };
                    ipList.Rows.Add(lineBuffer);

                }
                    progressBar.Invoke(new MethodInvoker(UpdateProgressBarByOne));
                    progressStatus.Text = ("Pinging IP " + count + " of 254");

            }
            button1.Enabled = true;
            progressBar.Invoke(new MethodInvoker(ResetProgressBar));

    }

2 个答案:

答案 0 :(得分:2)

看起来Ping有SendAsync功能。 This帖子(我知道它的vb,但只是为了得到一个想法)有一个例子。总之,只需更改Send to SendAsync并监听PingCompleted事件

即可

答案 1 :(得分:1)

我的建议是调查你的并发点。

首先,您将通过该线程访问任何对Windows窗体对象的访问权限。即你对button1的访问将在调试中抛出一个MDA,并可能在运行时随机崩溃。您必须使用委托并使用这样的模式在主线程上重新调用该方法。

this.Invoke(delgatetomyupdatermethod)

其次,你的时间花在ping本身上。所以我建议编写一个线程安全列表(只需编写一个带锁的方法

private object locker = new object();

private void InsertIntoList(string linebuffer)
{
    lock(locker)
    {
        ipList.Rows.Add(linebuffer);
    }
}

我建议使用.Net threadpool来运行你的方法来ping一个给定的IP。

要执行此操作,请编写一个函数,该函数将接受IP以进行ping并使用您的结果更新列表,然后通过对线程池中的项目进行排队来调用它。实际上,如果使用ManualResetEvent传入一个对象,您甚至可以编写代码来说明

System.Threading.WaitHandle[] waits = new System.Threading.WaitHandle[255];
//initialise the list of these and create the objects to ping.


foreach (var obj in mylistofobjectvalues)
{
    System.Threading.Threadpool.QueueUserWorkItem(method, obj);
}
System.Threading.WaitHandle.WaitAll(waits);

其中method是ping方法,obj包含一个带有manualresetevent的对象和你的方法需要ping它的目标的信息。

每次等待处理完成后,您都可以更新您的状态。通过GUI进行更多努力,您甚至可以让系统异步工作,以便在每个响应中更新您的gui,而不仅仅是在最后。