Suppose there is a ABCD.... sequence we want to print this sequence on Two threads. One thread printing in Upper case and another in Lower case without breaking the sequences or order.
Output should look like
A--thread1
a--thread2
B--thread1
b--thread2
C--thread1
c--thread2
Solution Code
using System;
using System.Threading;
class Program
{
static void Main()
{
Thread T1 = new Thread(new ThreadStart(Th1));
Thread T2 = new Thread(new ThreadStart(Th2));
T1.Start();
T2.Start();
}
static void Th1(){
string str ="ABCDEF" ;
foreach(char c in str){
Console.WriteLine(c.ToString().ToLower());
Thread.Sleep(1000);
}
}
static void Th2(){
string str ="ABCDEF" ;
foreach(char c in str){
Console.WriteLine(c);
Thread.Sleep(1000);
}
}
}
Output
A
a
B
b
C
c
Quick Notes for easy understanding. Chapters are on C#.Net,Linq,OOPS,Design Patterns,UML,Tools for development, Databases and many others. - Sid
Showing posts with label MULTI-THREADING. Show all posts
Showing posts with label MULTI-THREADING. Show all posts
Thursday, April 27, 2017
Monday, August 31, 2015
Brief about Multithreading
Asynchronous processing and background processing was always a must for serious programs serving complex user needs.
Threading design guidelines.
- Avoid providing static methods that mutate static state
- Design for server environment
- Instances do not need to be thread safe
- Static states must be thread safe
Timer threads
A common use of threads is for all kinds of periodical updates. Under Win32 we have two different ways: window timers and time limited waiting for events. .NET offers three different ways:
Windows timers with the System.WinForms.Timer class
Periodical delegate calling with System.Threading.Timer class (works on W2K only)
Exact timing with the System.Timers.Timer class
System.Timers.Timer class is the most complete solution for all time fired events. It gives you the most precise control and timing and is surprisingly simple to use.
- Create the Timer object. You can a use constructor with interval setting.
- Add your event handler (delegate) to the Tick event
- Set the Interval property to the desired number of milliseconds (default value is 100 ms)
- Set the AutoReset property to false if you want the event to be raised only once (default is true – repetitive raising)
- Start the ticking with a call to the Start() method, or by setting Enabled property to true.
- Stop the ticking with call to the Stop() method or by setting the Enabled property to false.
using System.Timers ;
void TickHandler( object sender, EventArgs e ){
// do some work
}
// usage block
{
...
// create timer
Timer kicker = new Timer() ;
kicker.Interval = 1000 ;
kicker.AutoReset = false ;
// add handler
kicker.Tick += new EventHandler( TickHandler ) ;
// start timer
kicker.Start() ;
// change interval
kicker.Interval = 2000 ;
// stop timer
kicker.Stop() ;
// you can start and stop timer againg
kicker.Start() ;
kicker.Stop() ;
...
}
I should mention a few things about using the Timers.Timer class:
- In VS Beta 1 you must add a reference to System.Timers namespace by hand.
- Whenever you use the Timers namespace together with System.WinForms or System.Threading, you should reference the Timer classes with the full name to avoid ambiguity.
- Be careful when using Timers.Timer objects. You may find them a lot faster than the old windows timers approach (think why). Do not forget synchronize data access.
Thread pooling
The idea for making a pool of threads on the .NET framework level comes from the fact that most threads in multithreaded programs spend most of the time waiting for something to happen. It means that thread entry functions contain endless loops which calls real working functions. By using the ThreadPool type object preparing working functions is simpler and for bonus we get better resource usage.
There are two important facts relating to ThreadPool object.
- There is only one ThreadPool type object per process
- There is only one working thread per thread pool object
The most useful use of a ThreadPool object is to add a new thread with a triggering event to the thread pool. i.e.. "when this event happens do this". For using ThreadPool this way you must perform following steps:
- Create event
- Create a delegate of type WaitOrTimerCallback
- Create an object which will carry status information to the delegate.
- Add all to thread pool
- Set event
// status information objectpublic class StatusObject{ // some information } // thread entry function public void someFunc( object obj, bool signaled ){ // do some clever work } // usage block { ... // create needed objects AutoResetEvent myEvent = new AutoResetEvent( false ) ; WaitOrTimerCallback myThreadMethod = new WairOrTimerCallback( someFunc ) ; StatusObject statusObject = new StatusObject() ; // decide how thread will perform int timeout = 10000 ; // timeout in ms bool repetable = true ; // timer will be reset after event fired or timeout // add to thread pool ThreadPool.RegisterWaitForSingleObject( myEvent, myThreadMethod, statusObject, timeout, repetable ) ; ... // raise event and start thread myEvent.Set() ; ... }
A less common use of a thread pool will be (or at least should be, be aware of misuse) adding threads to be executed when the processor is free. You could think of this kind of usage as "OK, I have this to do, so do it whenever you have time". Very democratic way of handling background processing which can stop your program quickly. Remember that inside the thread pool you have only one thread working (per processor).
Using thread pool this way is even simpler:
- Create a delegate of type WaitCallback
- Create an object for status information, if you need it
- Add to thread pool
// status information object
public class StatusObject{
// some information
}
// thread entry function
public void someFunc( object obj, bool signaled ){
// do some clever work
}
// usage block
{
...
// create needed objects
WaitCallback myThreadMethod = new WairOrTimerCallback( someFunc ) ;
StatusObject statusObject = new StatusObject() ;
// add to thread pool
ThreadPool.QueueUserWorkItem( myThreadMethod, statusObject ) ;
...
}
Some notes on thread pool:
- Don’t use a thread pool for threads that perform long calculations. You only have one thread per processor actually working.
- System.Thread.Timer type objects are one thread inside thread pool
- You have only one thread pool per process
Thursday, June 19, 2014
Thread Pool - BackgroundWorker
BackgroundWorker is a helper class in the
System.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
IComponentallowing 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:- Instantiate
BackgroundWorkerand handle theDoWorkevent. - Call
RunWorkerAsync, optionally with anobjectargument.
This then sets it in motion. Any argument passed to
RunWorkerAsync 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:
- Set the
WorkerReportsProgressproperty totrue. - Periodically call
ReportProgressfrom within theDoWorkevent handler with a “percentage complete” value, and optionally, a user-state object. - Handle the
ProgressChangedevent, querying its event argument’sProgressPercentageproperty. - Code in the
ProgressChangedevent 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:
- Set the
WorkerSupportsCancellationproperty totrue. - Periodically check the
CancellationPendingproperty from within theDoWorkevent handler. If it’strue, set the event argument’sCancelproperty totrue, and return. (The worker can also setCanceland exit withoutCancellationPendingbeingtrueif it decides that the job is too difficult and it can’t go on.) - Call
CancelAsyncto 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:
- Instantiate a delegate targeting the method you want to run in parallel (typically one of the predefined
Funcdelegates). - Call
BeginInvokeon the delegate, saving itsIAsyncResultreturn value.BeginInvokereturns immediately to the caller. You can then perform other activities while the pooled thread is working. - When you need the results, call
EndInvokeon the delegate, passing in the savedIAsyncResultobject.
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.
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. } } }
Subscribe to:
Posts (Atom)
Code Formater
| Paste Here Your Source Code | ||||||||||||||
| Source Code Formatting Options | ||||||||||||||
|
||||||||||||||
| Copy Formatted Source Code | ||||||||||||||
| Preview Of Formatted Code |