代码之家  ›  专栏  ›  技术社区  ›  user48202

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

  •  6
  • user48202  · 技术社区  · 16 年前

    我有一个应用程序可以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 回复  |  直到 16 年前
        1
  •  2
  •   SwDevMan81    16 年前

    看来平有一个 SendAsync 功能。 This Post(我知道它的vb,但只是想知道一个想法)有一个例子。总之,只需将发送更改为sendAsync并侦听pingCompleted事件即可。

        2
  •  1
  •   Spence    16 年前

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

    首先,您将遇到一个bug,可以在线程之外访问Windows窗体对象。也就是说,对button1的访问将在调试中引发一个MDA,并且可能在运行时随机崩溃。您必须使用委托,并使用这样的模式在主线程上重新调用该方法。

    this.Invoke(delgatetomyupdatermethod)
    

    第二,你的时间花在了乒乓球上。所以我建议编写一个线程安全列表(只需编写一个带有锁的方法

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

    我建议使用.NET线程池来运行方法,而不是ping给定的IP。

    要执行此操作,请编写一个函数,该函数将接收要Ping的IP,并用结果更新列表,然后通过对线程池上的项进行排队来调用它。事实上,如果你传入一个带有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);
    

    如果方法是ping方法,那么obj包含一个带有manualReseteEvent的对象,以及您的方法对其目标ping所需的信息。

    每次WaitHandle完成时,都可以更新状态。通过在GUI上做更多的工作,您甚至可以让系统异步工作,以便在每次响应时更新您的GUI,而不仅仅是在最后。