Showing posts with label THREADPOOL. Show all posts
Showing posts with label THREADPOOL. Show all posts

Thursday, June 19, 2014

Thread Pool - BackgroundWorker

BackgroundWorker is a helper class in theSystem.ComponentModel namespace for managing a worker thread. It can be considered a general-purpose implementation of the EAP, and provides the following features:
  • A cooperative cancellation model
  • The ability to safely update WPF or Windows Forms controlswhen the worker completes
  • Forwarding of exceptions to the completion event
  • A protocol for reporting progress
  • An implementation of IComponent allowing it to be sited in Visual Studio’s designer
BackgroundWorker uses the thread pool, which means you should never call Abort on a BackgroundWorker thread.

Using BackgroundWorker

Here are the minimum steps in using BackgroundWorker:
  1. Instantiate BackgroundWorker and handle the DoWork event.
  2. Call RunWorkerAsync, optionally with an object argument.
This then sets it in motion. Any argument passed toRunWorkerAsync will be forwarded to DoWork’s event handler, via the event argument’s Argument property. Here’s an example:
class Program  
 {  
  static BackgroundWorker _bw = new BackgroundWorker();  
  static void Main()  
  {  
   _bw.DoWork += bw_DoWork;  
   _bw.RunWorkerAsync ("Message to worker");  
   Console.ReadLine();  
  }  
  static void bw_DoWork (object sender, DoWorkEventArgs e)  
  {  
   // This is called on the worker thread  
   Console.WriteLine (e.Argument);    // writes "Message to worker"  
   // Perform time-consuming task...  
  }  
 }  
BackgroundWorker has a RunWorkerCompleted event that fires after the DoWork event handler has done its job. Handling RunWorkerCompleted is not mandatory, but you usually do so in order to query any exception that was thrown in DoWork. Further, code within a RunWorkerCompleted event handler is able to update user interface controls without explicit marshaling; code within the DoWork event handler cannot.
To add support for progress reporting:
  1. Set the WorkerReportsProgress property to true.
  2. Periodically call ReportProgress from within the DoWork event handler with a “percentage complete” value, and optionally, a user-state object.
  3. Handle the ProgressChanged event, querying its event argument’s ProgressPercentage property.
  4. Code in the ProgressChanged event handler is free to interact with UI controls just as withRunWorkerCompleted. This is typically where you will update a progress bar.
To add support for cancellation:
  1. Set the WorkerSupportsCancellation property to true.
  2. Periodically check the CancellationPending property from within the DoWork event handler. If it’s true, set the event argument’s Cancel property to true, and return. (The worker can also set Cancel and exit withoutCancellationPending being true if it decides that the job is too difficult and it can’t go on.)
  3. Call CancelAsync to request cancellation.
Here’s an example that implements all the preceding features:
   var bgWorker = new BackgroundWorker { WorkerReportsProgress = true };  
   bgWorker.DoWork += (o, e) =>  
   {  
     //Worker thread code. Gets called in a Non-UI thread.  
   };  
   bgWorker.ProgressChanged += (o, e) =>  
   {  
     //Progress change gets called on the UI thread. Controls can be accessed safely  
   };  
   bgWorker.RunWorkerCompleted += (o, e) =>  
   {  
     //gets called when worker thread finishes. UI thread. Controls can be accessed safely  
   };  
   bgWorker.RunWorkerAsync();  


 using System;  
 using System.Threading;  
 using System.ComponentModel;  
 class Program  
 {  
  static BackgroundWorker _bw;  
  static void Main()  
  {  
   _bw = new BackgroundWorker  
   {  
    WorkerReportsProgress = true,  
    WorkerSupportsCancellation = true  
   };  
   _bw.DoWork += bw_DoWork;  
   _bw.ProgressChanged += bw_ProgressChanged;  
   _bw.RunWorkerCompleted += bw_RunWorkerCompleted;  
   _bw.RunWorkerAsync ("Hello to worker");  
   Console.WriteLine ("Press Enter in the next 5 seconds to cancel");  
   Console.ReadLine();  
   if (_bw.IsBusy) _bw.CancelAsync();  
   Console.ReadLine();  
  }  
  static void bw_DoWork (object sender, DoWorkEventArgs e)  
  {  
   for (int i = 0; i <= 100; i += 20)  
   {  
    if (_bw.CancellationPending) { e.Cancel = true; return; }  
    _bw.ReportProgress (i);  
    Thread.Sleep (1000);   // Just for the demo... don't go sleeping  
   }              // for real in pooled threads!  
   e.Result = 123;  // This gets passed to RunWorkerCompleted  
  }  
  static void bw_RunWorkerCompleted (object sender,  
                    RunWorkerCompletedEventArgs e)  
  {  
   if (e.Cancelled)  
    Console.WriteLine ("You canceled!");  
   else if (e.Error != null)  
    Console.WriteLine ("Worker exception: " + e.Error.ToString());  
   else  
    Console.WriteLine ("Complete: " + e.Result);   // from DoWork  
  }  
  static void bw_ProgressChanged (object sender,  
                  ProgressChangedEventArgs e)  
  {  
   Console.WriteLine ("Reached " + e.ProgressPercentage + "%");  
  }  
 }  
Press Enter in the next 5 seconds to cancel
Reached 0%
Reached 20%
Reached 40%
Reached 60%
Reached 80%
Reached 100%
Complete: 123
 
Press Enter in the next 5 seconds to cancel
Reached 0%
Reached 20%
Reached 40%
 
You canceled!

Subclassing BackgroundWorker


BackgroundWorker is not sealed and provides a virtual OnDoWork method, suggesting another pattern for its use. In writing a potentially long-running method, you could write an additional version returning a subclassedBackgroundWorker, preconfigured to perform the job concurrently. The consumer then needs to handle only theRunWorkerCompleted and ProgressChanged events. For instance, suppose we wrote a time-consuming method called GetFinancialTotals:
 public class Client  
 {  
  Dictionary <string,int> GetFinancialTotals (int foo, int bar) { ... }  
  ...  
 }  
 We could refactor it as follows:  
 public class Client  
 {  
  public FinancialWorker GetFinancialTotalsBackground (int foo, int bar)  
  {  
   return new FinancialWorker (foo, bar);  
  }  
 }  
 public class FinancialWorker : BackgroundWorker  
 {  
  public Dictionary <string,int> Result;  // You can add typed fields.  
  public readonly int Foo, Bar;  
  public FinancialWorker()  
  {  
   WorkerReportsProgress = true;  
   WorkerSupportsCancellation = true;  
  }  
  public FinancialWorker (int foo, int bar) : this()  
  {  
   this.Foo = foo; this.Bar = bar;  
  }  
  protected override void OnDoWork (DoWorkEventArgs e)  
  {  
   ReportProgress (0, "Working hard on this report...");  
   // Initialize financial report data  
   // ...  
   while (!<finished report>)  
   {  
    if (CancellationPending) { e.Cancel = true; return; }  
    // Perform another calculation step ...  
    // ...  
    ReportProgress (percentCompleteCalc, "Getting there...");  
   }  
   ReportProgress (100, "Done!");  
   e.Result = Result = <completed report data>;  
  }  
 }  
Whoever calls GetFinancialTotalsBackground then gets a FinancialWorker: a wrapper to manage the background operation with real-world usability. It can report progress, can be canceled, is friendly with WPF and Windows Forms applications, and handles exceptions well.



BackgroundWorker and ProgressBar demo

public partial class Form1 : Form   
  {   
   public Form1()   
   {   
    InitializeComponent();   
    Shown += new EventHandler(Form1_Shown);   
    // To report progress from the background worker we need to set this property   
    backgroundWorker1.WorkerReportsProgress = true;   
    // This event will be raised on the worker thread when the worker starts   
    backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);   
    // This event will be raised when we call ReportProgress   
    backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);   
   }   
   void Form1_Shown(object sender, EventArgs e)   
   {   
    // Start the background worker   
    backgroundWorker1.RunWorkerAsync();   
   }   
   // On worker thread so do our thing!   
   void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)   
   {   
    // Your background task goes here   
    for (int i = 0; i <= 100; i++)   
    {   
     // Report progress to 'UI' thread   
     backgroundWorker1.ReportProgress(i);   
     // Simulate long task   
     System.Threading.Thread.Sleep(100);   
    }   
   }   
   // Back on the 'UI' thread so we can update the progress bar   
   void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)   
   {   
    // The progress percentage is a property of e   
    progressBar1.Value = e.ProgressPercentage;   
   }   
  }   

ThreadPool - Asynchronous delegates

ThreadPool - Asynchronous delegates

ThreadPool.QueueUserWorkItem doesn’t provide an easy mechanism for getting return values back from a thread after it has finished executing. Asynchronous delegate invocations (asynchronous delegates for short) solve this, allowing any number of typed arguments to be passed in both directions. Furthermore, unhandled exceptions on asynchronous delegates are conveniently rethrown on the original thread (or more accurately, the thread that callsEndInvoke), and so they don’t need explicit handling.

Here’s how you start a worker task via an asynchronous delegate:
  1. Instantiate a delegate targeting the method you want to run in parallel (typically one of the predefined Funcdelegates).
  2. Call BeginInvoke on the delegate, saving its IAsyncResult return value.

    BeginInvoke returns immediately to the caller. You can then perform other activities while the pooled thread is working.
  3. When you need the results, call EndInvoke on the delegate, passing in the saved IAsyncResult object.
In the following example, we use an asynchronous delegate invocation to execute concurrently with the main thread, a simple method that returns a string’s length:
static void Main()
{
  Func<string, int> method = Work;
  IAsyncResult cookie = method.BeginInvoke ("test", null, null);
  //
  // ... here's where we can do other work in parallel...
  //
  int result = method.EndInvoke (cookie);
  Console.WriteLine ("String length is: " + result);
}
 
static int Work (string s) { return s.Length; }
EndInvoke does three things. First, it waits for the asynchronous delegate to finish executing, if it hasn’t already. Second, it receives the return value (as well as any ref or out parameters). Third, it throws any unhandled worker exception back to the calling thread.

ThreadPool - QueueUserWorkItem

ThreadPool.QueueUserWorkItem

You can't use the Task Parallel Library if you're targeting an earlier version of the .NET Framework (prior to 4.0). Instead, you must use one of the older constructs for entering the thread pool: ThreadPool.QueueUserWorkItem and asynchronous delegates. The difference between the two is that asynchronous delegates let you return data from the thread. Asynchronous delegates also marshal any exception back to the caller.

QueueUserWorkItem

To use QueueUserWorkItem, simply call this method with a delegate that you want to run on a pooled thread:
static void Main()
{
  ThreadPool.QueueUserWorkItem (Go);
  ThreadPool.QueueUserWorkItem (Go, 123);
  Console.ReadLine();
}
 
static void Go (object data)   // data will be null with the first call.
{
  Console.WriteLine ("Hello from the thread pool! " + data);
}

Our target method, Go, must accept a single object argument (to satisfy the WaitCallback delegate). This provides a convenient way of passing data to the method, just like with ParameterizedThreadStart. Unlike with Task,QueueUserWorkItem doesn't return an object to help you subsequently manage execution. 

We must use WaitCallback. At MSDN, WaitCallback is described as a delegate callback method to be called when the ThreadPool executes. It is a delegate that "calls back" its argument.
WaitCallback
You can use WaitCallback by simply specifying the "new WaitCallback" syntax as the first argument to ThreadPool.QueueUserWorkItem. You don't need any other code to make this approach effective.


public partial class MainWindow : Form
{
    // This is the delegate that runs on the UI thread to update the bar.
    public delegate void BarDelegate();
 
    // The form's constructor (autogenerated by Visual Studio)
    public MainWindow()
    {
                InitializeComponent();
    }
 
    // When a buttom is pressed, launch a new thread
    private void button_Click(object sender, EventArgs e)
    {
                // Set progress bar length.
                progressBar1.Maximum = 6;
                progressBar1.Minimum = 0;
 
                // Pass these values to the thread.
                ThreadInfo threadInfo = new ThreadInfo();
                threadInfo.FileName = "file.txt";
                threadInfo.SelectedIndex = 3;
 
                ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessFile), threadInfo);
    }
 
    // What runs on a background thread.
    private void ProcessFile(object a)
    {
                // (Omitted)
                // Do something important using 'a'.
 
                // Tell the UI we are done.
                try
                {
                    // Invoke the delegate on the form.
                    this.Invoke(new BarDelegate(UpdateBar));
                }
                catch
                {
                    // Some problem occurred but we can recover.
                }
    }
 
    // Update the graphical bar.
    private void UpdateBar()
    {
                progressBar1.Value++;
                if (progressBar1.Value == progressBar1.Maximum)
                {
                    // We are finished and the progress bar is full.
                }
    }
}







Code Formater

Paste Here Your Source Code
Source Code Formatting Options
1) Convert Tab into Space :
2) Need Line Code Numbering :
3) Remove blank lines :
4) Embeded styles / Stylesheet :
5) Code Block Width :
6) Code Block Height :
7) Alternative Background :
Copy Formatted Source Code
 
Preview Of Formatted Code