Wednesday, September 19, 2012

Multithreading in WPF (Windows Presentation Foundation) PART : 1

Hello Friends,

In my this post i will explain Multithreading from very beginning. As we all must have heard the term 'Thread'. We know that whenever we want to do parallel processing we uses threads.
So lets start from the basic building block needed to understand implementation of multithreading in WPF application.Once we know the basic logic behind Parallel programming it can be used in any kind of application.Here i will use C# language to give examples or sample codes.

Suppose we have an application that have many modules in it . It may include long running tasks,few tasks which needs user interactions or anything else. If we want to implement threading then we must know that which weapon we will use to hit the problem in the best way. :)

Few of the weapons for you guys are ---

  •  Background Worker
  • Thread
  • Thread pool
  • I will also explain about Dispatcher timer because wherever we need to run certain piece of code after an interval then we uses timers. In WPF we uses Dispatcher timer.
Lets begin in detail one by one,

Background worker :

We uses background worker where we need to seperate a task from our main running thread.
 Let me explain it in more simple words.....Suppose we have an application in which we want to run a task in background and just want to make it complete without any disturbance then we can put that piece of code in background worker's DoWork eventhandler.
Before using this we must know few very basic and very important points about it and they are -
                  BackgroundWorker mybgworker = new BackgroundWorker();
  • How to use its properties & mots important its events :-
                    mybgworker.WorkerSupportsCancellation = true;
                   mybgworker.WorkerReportsProgress = true;
-----//DoWork : this is the most important eventhandler all the tasks you want to do in background worker must be written in this.
          mybgworker.DoWork += new DoWorkEventHandler(mybgworker_DoWork);
mybgworker.ProgressChanged += new ProgressChangedEventHandler(mybgworker_ProgressChanged);
mybgworker.RunWorkerCompleted +=  new RunWorkerCompletedEventHandler(mybgworker_RunWorkerCompleted);

----If you wants to have access to cancel background worker processing at any moment from your code then you must need to enable this property as true. ( For ex: On a Cancel buton's Click you want to cancel background worker)

private void mybgworker_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;

    for (int k = 1; (k <= 10); k++)
    {
        if ((worker.CancellationPending == true))
        {
            e.Cancel = true;
            break;
        }
        else
        {
          
            System.Threading.Thread.Sleep(500);
            worker.ReportProgress((k * 10));
        }
    }
}

--- If you wants to keep on checking progress of your background worker then you can set reports progress property true.(For ex: you want to run your progress bar in background then you can check at any state of processing.)
private void mybgworker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    this.txtProgress.Text = (e.ProgressPercentage.ToString() + "%");
}
-----Runworkercompleted is used if you want to do something at the timewhene worker has been finished its work.
 private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
 {
//----write your code here friends....
 } 
Everything is useless if your wont start running this worker by writing 
           mybgworker.RunWorkerAsync();
  • Now comes the logical part -----
IF YOU KNOW THE LOGIC YOU CAN IMPLEMENT THREADING IN ANY APPLICATION
 -------------------------------------------------------------->>
*  If one thread is running and doing certain tasks and during its processing it is accessing certain objects, UI elements then any other thread can not access it.This is the basic and main logic in the processing of thread.It is also called thread affinity.
*If you are using multithreading in your code and you want to access any object or UI element which might be also been accessed by some other thread parallel or not.You have to use Dispatcher to access it else you will get following exception :
    The calling thread cannot access this object because a different thread owns it.

this.Dispatcher.Invoke(
            new Action(() =>
            { //write your code here friends...... }));

* Before adding any method in Thread Remember to make its state ( Apartment state )  as STA like this.
     Thread th =  new Thread(Write your methodname here );
       th.SetApartmentState(ApartmentState.MTA);
If you will not add this line then you will get this exception :
   The calling thread must be STA, because many UI components require this.

*  In WPF if you are using multi threading then NEVER access your controls without dispatcher else you will definitely get exceptions
------------------------------------------------------------<<
  • Lets come back to our backgroundworker part,so in actual background worker itselef runs in a seperate thread so if you are trying to access any object/UI component in its DoWork then you must have to use dispatchers.
  • You can use any control any method anything without dispatcher in RunWorkerCompleted as at time thread of backgroundworker has been ended.
By taking care of only these few little but most important fundas to implement threads.
This was the PART One explaining basic concepts to implement threading using background worker.I will explain Thread and threadpool in my next parts of this post.
Thanks & Regards,
Pragya Sharma
Software Engineer
INDIA



1 comment: