C# Ping code performance

MSDN has an async example I think. Thanks, I think I'm fine though. Dequadins code above is already threaded, so I'll probably use that.
Of course asynchronous under the covers also uses threading. If you don't come right and want to try threading pm me.
 
Anyway I threw together a very rough example of basic threading.
Using 40 threads, the results are delivered in ~7 seconds.

Code:
using System;
using System.Collections;
using System.Net.NetworkInformation;
using System.Threading;

namespace PingThreading
{
    class Program
    {
        public static Queue targets = Queue.Synchronized(new Queue());
        public static Queue results = Queue.Synchronized(new Queue());

        static void Main(string[] args)
        {
            DateTime start = DateTime.Now;

           [B]//Load ipaddresses into targets queue[/B]
            for (int i = 1; i < 255; i++)
            {
                targets.Enqueue(string.Format("192.168.0.{0}", i));
            }

            int threadIsAliveCount = 0;

           [B]//Specify number of threads[/B]
            Thread[] t = new Thread[40];

           [B]//Start up the threads[/B]
            for (int i = 0; i < t.Length; i++)
            {
                t[i] = new Thread(new ThreadStart(pinger));
                t[i].Start();
                threadIsAliveCount++;
            }

            [B]//Loop if threads are still active[/B]
            while (threadIsAliveCount > 0)
            {
                threadIsAliveCount = 0;
                foreach (Thread et in t)
                {
                    if (et.IsAlive)
                    {
                        threadIsAliveCount++;
                    }
                }

                [B]//Dequeue results and output to console[/B]
                while (results.Count > 0)
                {
                    Console.WriteLine("{0}", results.Dequeue());
                }
            }

            Console.WriteLine("All done, elapsed seconds = {0}",
                    DateTime.Now.Subtract(start).Seconds);
        }

        [B]//Action module executed by each thread[/B]
        static void pinger()
        {
            while (targets.Count>0)
            {
                string addr = targets.Dequeue().ToString();
                if (new Ping().Send(addr, 1000).Status == IPStatus.Success)
                {
                    results.Enqueue(addr);
                }
            }

            [B]//Delay thread termination by 500ms to allow dequeueing of results.[/B]
            Thread.Sleep(500);
        }
    }
}
 
Last edited:
Nice thread guys!

I got bored earlier and threw together a test case. Result: 01.7708627 ~1.8seconds

I used a SynchronizedCollection here to accumulate the results, spawned a seperate thread for each IPAddress and a separate thread to monitor the progress. Normally you would not spin up so many threads, but as the limit here will never go above 256 threads, and they won't be alive for very long, it can be acceptable if you are gunning for performance as a primary factor. Remember that each thread you spin up can take up to a MB of virtual memory, so this example i've pasted is very specific to this scenario.

For this example, I created a WPF application, and added System.ServiceModel as a reference to the app. I don't like console apps so I made mine a real one:P

Code:
#region Directives

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.NetworkInformation;
using System.Threading;
using System.Windows;

#endregion Directives

namespace PingTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        #region Fields

        // boolean used to exit the tracking thread
        bool _isChecking = true;
        // Stopwatch to monitor performance
        Stopwatch sw = new Stopwatch();

        #endregion Fields


        #region Properties

        // Thread safe synchronised collection... a lot faster than using lock(){}
        private SynchronizedCollection<PingResult> ResultCollection
        {
            get
            {
                if (_ResultCollection == null)
                {
                    _ResultCollection = new System.Collections.Generic.SynchronizedCollection<PingResult>();
                }
                return _ResultCollection;
            }
            set
            {
                _ResultCollection = value;
            }
        }
        private SynchronizedCollection<PingResult> _ResultCollection;

        #endregion Properties


        #region Constructor Methods

        public MainWindow()
        {
            InitializeComponent();

            // Start spinning threads
            PingAddresses();

            // Start tracking progress
            SpawnTrackingThread();
        }

        #endregion Constructor Methods


        #region Methods

        /// <summary> Method that spawns threads. It's not ideal to spawn this many threads... but as the threads spend most of their time waiting for a ping reply 
        /// as opposed to processing, it's not that bad. Also, for this situation, we won't go over 256 threads, so it can be justified in the interest of performance
        /// </summary>
        private void PingAddresses()
        {
            sw.Start();

            for (int i = 0; i < 256; i++)
            {
                string ipAddress = string.Format("192.168.0.{0}", i);
                System.Threading.Thread thread = new System.Threading.Thread(
                   new System.Threading.ThreadStart(
                     delegate()
                     {
                            Ping ping = new Ping();
                            PingOptions options = new PingOptions
                            {
                                DontFragment = true
                            };

                            byte[] buffer = new byte[32];
                            int timeout = 120;
                            try
                            {
                                PingReply reply = ping.Send(ipAddress, timeout, buffer, options);
                                bool result = reply.Status == IPStatus.Success;
                                PingResult pingResult = new PingResult(ipAddress, result);
                                ResultCollection.Add(pingResult);
                            }
                            catch
                            {
                            }
                     }
                ));

                thread.Start();
            }
            
        }

        private void SpawnTrackingThread()
        {
            Thread thread = new Thread(new ThreadStart(CheckingThread));
            thread.IsBackground = true;
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
        }

        /// <summary> Use a tracking thread to monitor the progress of the main thread.
        /// This way we do not need to check on every iteration which will slow the processing down considerably
        /// </summary>
        private void CheckingThread()
        {
            while (_isChecking == true)
            {
                if (_ResultCollection.Count == 254)
                {
                    sw.Stop();

                    Application.Current.Dispatcher.BeginInvoke((Action)(() =>
                    {
                        // Dispatch the UI updates back onto the UI Thread
                        for (int i = 0; i < _ResultCollection.Count; i++)
                        {
                            Console.WriteLine("{0} {1}", _ResultCollection[i].IPAddress, _ResultCollection[i].Result);
                        }
                        Console.WriteLine("{0}", sw.Elapsed);
                    }));

                    _isChecking = false;
                    Thread.Sleep(50);
                }
            }
        }

        #endregion Methods
    }

    /// <summary> Result Container
    /// </summary>
    public class PingResult
    {

        #region Properties

        public string IPAddress
        {
            get;
            set;
        }

        public bool Result
        {
            get;
            set;
        }

        #endregion Properties


        #region Constructor Methods

        public PingResult()
        {

        }

        public PingResult(string ipAddress, bool result)
        {
            IPAddress = ipAddress;
            Result = result;
        }

        #endregion Constructor Methods

    }
}
 
Last edited:
You're only going to scare him further with that example -- hence I went for shorter.

Btw you need to avoid the bottom and top addresses of a subnet (network and broadcast) -- no host can be allocated these addresses.
 
Last edited:
[)roi(];7361277 said:
You're only going to scare him further with that example -- hence I went for shorter.

Depends on how quickly he wants to learn threading... he now has a number of personalised examples to choose from:P

plus I was bored... and it was a challenge.
 
Top
Sign up to the MyBroadband newsletter
X