C# MultiThreading Using ThreadPool, Anonymous Delegates and Locks

What is the quickest, least lines of code, way of creating a thread in ones code?

The answer is to create an anonymous delegate and pass it over to the ThreadPool object. Below is a class comically called DirtyPool which demonstrates these items:

  1. Self contained code, call the static ShowExample to run the console example.
  2. Uses three threads, two to generate data and one to write it out.
  3. Calls QueueUserWorkItem off of the ThreadPool to launch the threads.
  4. Demonstrates thread safe access to shared resource by using lock.

Here is the quick code example:

public class DirtyPool
{
    // Data held in this queue.
    public static Queue<string> _Operations
                      = new Queue<string>();

    // Status objects for printer delegate/thred
    // to know when to exit.
    bool OneEnded;
    bool TwoEnded;

    public static void ShowExample()
    {
        DirtyPool dp = new DirtyPool();
        dp.DoIt();
        // Sleep long enough so not to kill the threads.
        Thread.Sleep( 10000 );
    }

    public  void SetData( string who )
    {
        lock ( _Operations )
            _Operations.Enqueue( who );

    }

    public  void PrintData( )
    {
        lock ( _Operations )
            if (_Operations.Count > 0)
                Console.WriteLine( _Operations.Dequeue() );

    }

    public void DoIt()
    {

    ThreadPool.QueueUserWorkItem(
        delegate // Anonomous Delegate For Creation 1
        {

            for ( int index = 0; index < 5; ++index )
            {
                Thread.Sleep( 1500 );
                SetData( "Pool 1: " + index  );
            }
            OneEnded = true;
        }
    );

    ThreadPool.QueueUserWorkItem(
       delegate // Anonomous Delegate For Creation 2
       {
           for ( int index = 0; index < 5; ++index )
           {
               Thread.Sleep( 1000 );
               SetData( "Pool 2: " + index );
           }

           TwoEnded = true;

       }
   );

    ThreadPool.QueueUserWorkItem(
            delegate // Anonomous Delegate For Extraction & Printing
            {
             while ( !( TwoEnded && OneEnded ) )
                 PrintData();

             PrintData(); // Just in case...

            }
        );

    }

}

Here is the output:

Pool 2: 0

Pool 1: 0Pool 2: 1

Pool 1: 1

Pool 2: 2

Pool 2: 3

Pool 1: 2

Pool 2: 4

Pool 1: 3

Pool 1: 4

Press any key to continue . . .

 

Share

2 Comments

  1. Andrew says:

    Hi,

    For locking it’s better to use dedicated private fields – your _Operations is public and hence other threads can lock on it as well.

    Other than that, nice post! :)

    Regards,
    Andrew

  2. I think that making _Operations a readonly field would be better though. I usually do use dedicated private fields for locking, but considering that the geniality of this solution is achieving something somewhat complex as synchronizing severall threads through this simplicity, I would try to still keep things as simple as possible.

    Liked this post a lot. Keep them coming William :)

Leave a Reply to Andrew