Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert Ping application to multithreaded version to increase speed - C#

I have an application that pings every possible IP on your local subnet in order to compile a list of responsive IP addresses. Currently it pings all 255 one at a time. Is it possible to convert this app to use multiple threads to increase the speed by pinging more than one at a time? I am new to the concept of multiple threads and figure this would be a good way to learn(as long as it's possible of course).

also, any stylistic improvements you can educate me on would also be helpful.

thanks ahead of time

Here is the current pinging method in a backgroundWorker1_DoWork event.

        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));

    }
like image 527
user48202 Avatar asked Jan 22 '10 01:01

user48202


2 Answers

It looks like Ping has a SendAsync function. This post (I know its vb, but just to get an idea) has an example. In summary, just change your Send to SendAsync and listen for the PingCompleted event

like image 80
SwDevMan81 Avatar answered Nov 02 '22 06:11

SwDevMan81


Well my advice is to look into your concurrency points.

Firstly you will hit a bug with any access to windows forms objects off the thread. i.e your access to button1 WILL throw an MDA in debug, and might crash at runtime randomly. You have to use a delegate and invoke the method back on the main thread using a pattern like this.

this.Invoke(delgatetomyupdatermethod)

Secondly, your time is spent in the ping itself. So I would recommend writing a threadsafe list (just write a method with a lock on it

private object locker = new object();

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

I would recommend using the .Net threadpool to run your method instead to ping a given IP.

To do this write a function that will take in the IP to ping and to update the list with your result, then call it by queueing up items on the threadpool. Indeed if you pass in an object with a ManualResetEvent you can even write your code to say

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);

where method is the ping method, obj contains an object with the manualresetevent and information your method needs to ping it's target.

Each time your waithandle completes you can update your state. With some more effort on your GUI you could even have the system working asynchronously, so that your gui is updated on each response, not just at the end.

like image 27
Spence Avatar answered Nov 02 '22 06:11

Spence