Преобразование приложения Ping в многопоточную версию для увеличения скорости-C#

У меня есть приложение, которое пингует каждый возможный IP-адрес в вашей локальной подсети, чтобы скомпилировать список отзывчивых IP-адресов. В настоящее время он пингует все 255 по одному. Можно ли преобразовать это приложение для использования нескольких потоков, чтобы увеличить скорость, пингуя более одного за раз? Я новичок в концепции нескольких потоков и считаю, что это был бы хороший способ узнать(насколько это возможно, конечно).

кроме того, любые стилистические улучшения вы можете обучить меня также было бы полезно.

превосходно!

вот текущий метод pinging в событии backgroundWorker1_DoWork.

        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 ответов


похоже, что у Ping есть SendAsync


Ну, мой совет-посмотреть на ваши точки параллелизма.

во-первых, вы нажмете ошибку с любым доступом к объектам windows forms из потока. Я. e ваш доступ к button1 будет бросать MDA в debug и может аварийно завершиться во время выполнения. Вы должны использовать делегат и вызвать метод обратно в основной поток, используя такой шаблон.

this.Invoke(delgatetomyupdatermethod)

во-вторых, время тратится на сам пинг. Поэтому я бы рекомендовал написать список threadsafe (просто напишите метод с замком на нем

private object locker = new object();

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

Я бы рекомендовал использовать .Net threadpool для запуска вашего метода вместо ping данного IP.

для этого напишите функцию, которая будет принимать IP-адрес для ping и обновлять список с вашим результатом, а затем вызывать его, выстраивая в очередь элементы на threadpool. Действительно, если вы передаете объект с помощью 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 содержит объект с manualresetevent и информация, которую ваш метод должен пинговать, это цель.

каждый раз, когда ваш waithandle завершает вы можете обновить свое состояние. С некоторыми усилиями на вашем GUI вы могли бы даже иметь систему, работающую асинхронно, так что ваш gui обновляется на каждом ответе, а не только в конце.