views:

488

answers:

2

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

    }
+2  A: 

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

SwDevMan81
+1  A: 

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.

Spence
I'm sure this makes complete sense, I just have no idea what it says, lol. Sorry if I'm remedial, this solution is over my head, which probably means my question is over my head also.
jon
how do I pass an argument while invoking a method like this ipList.Invoke(new MethodInvoker(UpdateIpList(lineBuffer))); It keeps telling me "UpdateIpList(lineBuffer)" isn't a method.
jon
Windows forms and threads aren't easy to do. same thing with concurrency, it takes a bit of learning to get it right. I highly recommend "Programming Visual C# 2008 the base class library" which has a great intro to threading (and all the good parts of the framework too.)
Spence
it will take "UpdateIpList" just fine but when I try to write the method to accept an argument, it won't let me, and I'm needing to pass the info out.
jon