Multithreaded ping sweeping in VB.NET 2005

by Pber July 21, 2009 20:44

Multithreading

Learning multithreading is not one of the easiest things to do.  Microsoft made it much easier to implement with the .NET framework, but it's still not a small undertaking.  One of the challenges I found when first learning multithreading was trying to find good examples.  There are a lot of them out there.  They were either too easy or too hard and complex for the beginner to understand without getting confused by the code.  The easy ones are good for getting the principals down, but didn't demonstrate how to get real data into a thread or data out of a thread.

I wanted to try and develop something middle of the road.  So I decided to make a ping sweep application that could ping a range of IPs and report back the ping result information and place it into a listview.  I also wanted to add options to either select the use of no threading, Free threading, and thread pools.  I will discuss each of these next.  I chose not to include the backgroundworker class in this application as it caused some difficulties integrating into my existing methods and procedures and caused some complexity that I was trying to avoid in the first place.  The demo also takes advantage of the flicker free listview as discussed in my article here.

The ping sweep timings for each of these next methods were done on a class C subnet of 254 hosts with about 80% of the hosts online using a packet size of 32 bytes and a ping time out of 1000ms.

No Threading

This method just runs on the User Interface (UI) thread.  This usually involves a loop  or a long math calculation that update come control.  During its execution, the UI is essentially blocked and the user can't click anything until the processing is complete.  This is why we want to do multithreading.  With multithreading, we can do other things while tasks such as long math calculation, file transfers, or many pings are done in the background.  Using the ping sweeping demo program to ping my test subnet using no threading, it takes around 60 seconds to complete the ping sweep. 

Free Threading

I refer to free threading as just creating as many threads as you need.   In the ping sweeping demo application, using the free threading method will create as many ping threads as you have hosts.  This has an advantage of being extremely fast.  Ping sweeping the same subnet as in the previous example takes about 2 seconds using free threading.  Had it not completed so quickly, you would have noticed the GUI remained responsive.  Nice performance increase, but there is also a downside to this.  You can easily swamp the CPU or memory resources by rapidly spawning so many threads.  Using this method, if you attempted to ping sweep 2500 hosts you will likely deplete your CPU and memory to the point of throwing an out of memory exception.

There is also another downside of spawning so many threads that update the GUI.  In .NET, controls on the UI can only be updated by the thread they were created on.  When you spawn new threads, the only way to update controls on the UI is to marshall the data back to the UI thread via a delegate sub that runs on the UI thread.  So when you spawn lots of threads, you can end up with the UI thread being swamped as too many worker threads are trying to marshall data back all a once.

You could build your own thread control where you keep track of the number of threads you are running and throttle the amount of threads you create, but this could get complex.  So what do we do.  Use a threadpool.

ThreadPools

Threadpools are queues and are used almost the same as free threading.  Instead of creating a thread to point to your function then starting each thread, you just place the pointer to your function in a threadpool.  The threadpool will then take care of processing each thread and control how many threads can run at once.  The advantage of this is you now don't swamp your CPU or memory resources and still take advantage using threading to keep your GUI responsive.  The downside is you will lose a little speed as not as many threads are running at once, however you can also control the amount of threads that a threadpool uses.  By default it uses 25 threads per CPU.  Ping sweeping the same subnet in the previous two examples takes about 8 seconds using a threadpool of 25 threads.

Keeping track of threads

Now that you have a bunch of threads running, how do you keep track of them to know when they are all done.  I chose to use the Interlocked class.  It provided the ability to increment or decrement a threadcount variable in a thread safe way.  So as I spawned each thread I would call the increment method of the interlocked class to increase the threadcount variable.  As each thread completes, I would call the decrement method of the interlocked class  to decrease the threadcount variable.  When the threadcount variable reaches 0, all threads are done. 

Enough talk

Here's my demo ping sweeper written in VB.NET 2.0.  Have a look at the code, I hope I explained it well enough here as well as in the code comments.  Give it a try and let me know what you think.

PingSweeperv1.0_Demo.zip (21.23 kb)

Tags: , ,

Programming

Comments

9/18/2009 3:47:02 PM #

It still floors me why people give away free tools, let alone the source code.  It's way faster than any other one I've tried.

Thanks, awesome work.

alex United States

9/18/2009 5:44:12 PM #

Glad to help

Pber Canada

4/13/2010 7:39:59 AM #

Thanks for posting this. Very descriptive, and informative. I'm just learning out in .Net after using VB6 for many years, and have found your articles aimed at the right pitch.

Much impressed.

Chris United Kingdom

Add comment




  Country flag

biuquote
  • Comment
  • Preview
Loading



Powered by BlogEngine.NET 1.6.1.0
Theme by Mads Kristensen | Modified by Pber