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

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

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

спасибо заранее

Вот текущий метод проверки связи в событии 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 ]

2 голосов
/ 22 января 2010

Похоже, что Ping имеет функцию SendAsync . В этом посте (я знаю его vb, но только для того, чтобы понять) есть пример. Таким образом, просто измените свой Send на SendAsync и прослушайте событие PingCompleted

1 голос
/ 22 января 2010

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

Во-первых, вы столкнетесь с ошибкой при любом доступе к объектам оконных форм вне потока. т. е. ваш доступ к кнопке 1 будет вызывать MDA при отладке и может случайно произойти во время выполнения. Вы должны использовать делегат и вызывать метод обратно в главном потоке, используя такой шаблон:

this.Invoke(delgatetomyupdatermethod)

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

private object locker = new object();

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

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

Для этого напишите функцию, которая примет 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);

где method - метод ping, obj содержит объект с manualresetevent и информацию, необходимую вашему методу для пингования его цели.

Каждый раз, когда ваша ручка ожидания завершается, вы можете обновить свое состояние. Если приложить больше усилий к графическому интерфейсу, система может работать асинхронно, чтобы обновлять графический интерфейс при каждом ответе, а не только в конце.

...