Posts Tagged MultiThreading

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

Tags: ,

Safely Update .Net Winform from Threads or Timer Ticks

Update The following article is one way to to achieve threading…But an easier way to try first is the BackGround Worker component (How to: Run an Operation in the Background). The below article shows how to invoke back to the form which is a step one does not have to do directly with the background worker due to its design.
Whenever one has threads or timers doing work on a winform application there is a need to update the screen from those operations. Most first time winform programmers fall into the trap where they try to update a screen control from those background processes and discover that their app locks up. The reason is that any data screen updating needs to be done by the GUI thread solely and not from any background task.
What the code should do is invoke a delegate back to the GUI thread to do the screen updating. This article shows one such way.
Step 1 define a delegate on the winform form class, and have an event derived from it which can be subscribed to such as:
// This is the format the delegate method
// will use when invoking back to the main gui
// thread.
public delegate void DataAcquired( object sender );
// The main thread will check for events
// invoked by subscribed threads here.
// This is the subscription point for the 
// threads.
public event DataAcquired OnDataAcquiredEvent;

In the above example we are just using an object to pass between the threads, but you can specify anything you want which is dictated by your circumstances.

Step 2 then have the form subscribe to the event (as in the constructor) which will be eventually be consumed by the worker threads or timers.

OnDataAcquiredEvent +=
    new DataAcquired(ThreadReportsDataAquiredEvent);

Note intellisense will do the above steps for you after the +=, accept them and it will do the next step

Step 3 Create the method that will handle the GUI update event

private void ThreadReportsDataAquiredEvent( object sender )
{
   tsslStatus.Text = sender.ToString();
}
  • Line 01: The thread/timer passes in an object which we will use to update the screen.
  • Line 03: We will take the object’s information from its ToString() and place it on a label on the form for the end user to see.

Step 4: In the timer tic method or the worker thread method we will call this method which will invoke back to the main thread:

private void PushStatus(string status)
{
    this.Invoke(this.OnDataAcquiredEvent,
                new object[] { status });
}

Note: One doesn’t have to create a separate method; the invoke line is all one has to do. We create the event and fire it to the GUI thread.

That is a safe way to update the screen for worker threads or timer tick events.

Share

Tags: , , , , ,