|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
SummaryThis article describes thread basics covering the following areas:
Thread Synchronization is explained covering the following:
OverviewIn this article, we are going to look into the basics and advance concepts about Microsoft .NET Framework based Threading support. Refer to the previous article for details about the Microsoft .NET framework. Threading is one of the integral parts of the Microsoft .NET Framework based Common Language Runtime. Refer to the previous article on .NET Framework for more details.
Architecture of CLRThreading support is in-built under the Common Language Runtime provided by the Microsoft .NET Framework. Understanding Threading
Working with ThreadsCreate a new instance of the Example: Thread myThread = new Thread( new ThreadStart(myFunc) );
To run this thread, we need the following: Thread t1 = new Thread( new ThreadStart(Incrementer) );
To instantiate this, we need the following: t1.Start( );
A detailed example is as below: namespace Programming_CSharp
{
using System;
using System.Threading;
class Tester
{
static void Main( )
{
// make an instance of this class
Tester t = new Tester( );
// run outside static Main
t.DoTest( );
}
public void DoTest( )
{
// create a thread for the Incrementer
// pass in a ThreadStart delegate
// with the address of Incrementer
Thread t1 = new Thread(new ThreadStart(Incrementer) );
// create a thread for the Decrementer
// pass in a ThreadStart delegate
// with the address of Decrementer
Thread t2 = new Thread(new ThreadStart(Decrementer) );
// start the threads
t1.Start( );
t2.Start( );
}
// demo function, counts up to 1K
public void Incrementer( )
{
for (int i =0;i<1000;i++)
{
Console.WriteLine("Incrementer: {0}", i);
}
}
// demo function, counts down from 1k
public void Decrementer( )
{
for (int i = 1000;i>=0;i--)
{
Console.WriteLine("Decrementer: {0}", i);
}
}
}
}
Output: Incrementer: 102
Incrementer: 103
Incrementer: 104
Incrementer: 105
Incrementer: 106
Decrementer: 1000
Decrementer: 999
Decrementer: 998
Decrementer: 997
Joining ThreadsOnce a thread starts running and in some situation if we need to tell the thread to stop processing and wait until a second thread completes processing, we need to join the first thread to the second thread. Use the following for the same. This will join the second thread to the first one. Example: t2.Join( );
Suspending the ThreadIn some situations, we might want to suspend a running thread. Example: t2..Sleep(<No of Seconds>);
Killing a ThreadThreads has to die after the execution of the process in normal situations, occasionally it is required for the programmer to kill a thread. Threads can be killed using the following: Example: t2.Abort();
Advanced ThreadingSynchronizationIn some situations, we need to synchronize the running threads so we can modify the running thread and its resources. namespace Programming_CSharp
{
using System;
using System.Threading;
class Tester
{
private int counter = 0;
static void Main( )
{
// make an instance of this class
Tester t = new Tester( );
// run outside static Main
t.DoTest( );
}
public void DoTest( )
{
Thread t1 = new Thread( new ThreadStart(Incrementer) );
t1.IsBackground=true;
t1.Name = "ThreadOne";
t1.Start( );
Console.WriteLine("Started thread {0}",
t1.Name);
Thread t2 = new Thread( new ThreadStart(Incrementer) );
t2.IsBackground=true;
t2.Name = "ThreadTwo";
t2.Start( );
Console.WriteLine("Started thread {0}", t2.Name);
t1.Join( );
t2.Join( );
// after all threads end, print a message
Console.WriteLine("All my threads are done.");
}
// demo function, counts up to 1K
public void Incrementer( )
{
try
{
while (counter < 1000)
{
int temp = counter;
temp++; // increment
// simulate some work in this method
Thread.Sleep(1);
// assign the decremented value
// and display the results
counter = temp;
Console.WriteLine("Thread {0}. Incrementer: {1}",
Thread.CurrentThread.Name, counter);
}
}
catch (ThreadInterruptedException)
{
Console.WriteLine("Thread {0} interrupted! Cleaning up...",
Thread.CurrentThread.Name);
}
finally
{
Console.WriteLine("Thread {0} Exiting. ", Thread.CurrentThread.Name);
}
}
}
}
Output: >Started thread ThreadOne
Started thread ThreadTwo
Thread ThreadOne. Incrementer: 1
Thread ThreadOne. Incrementer: 2
Thread ThreadOne. Incrementer: 3
Thread ThreadTwo. Incrementer: 3
Thread ThreadTwo. Incrementer: 4
Thread ThreadOne. Incrementer: 4
Thread ThreadTwo. Incrementer: 5
Thread ThreadOne. Incrementer: 5
Thread ThreadTwo. Incrementer: 6
Thread ThreadOne. Incrementer: 6
Using Interlock
Example: public void Incrementer( )
{
try
{
while (counter < 1000)
{
Interlocked.Increment(ref counter);
// simulate some work in this method
Thread.Sleep(1);
// assign the decremented value
// and display the results
Console.WriteLine("Thread {0}. Incrementer: {1}",
Thread.CurrentThread.Name, counter);
}
}
}
Output (excerpts): Started thread ThreadOne
Started thread ThreadTwo
Thread ThreadOne. Incrementer: 1
Thread ThreadTwo. Incrementer: 2
Thread ThreadOne. Incrementer: 3
Thread ThreadTwo. Incrementer: 4
Thread ThreadOne. Incrementer: 5
Thread ThreadTwo. Incrementer: 6
Thread ThreadOne. Incrementer: 7
Thread ThreadTwo. Incrementer: 8
Thread ThreadOne. Incrementer: 9
Thread ThreadTwo. Incrementer: 10
Thread ThreadOne. Incrementer: 11
Thread ThreadTwo. Incrementer: 12
Thread ThreadOne. Incrementer: 13
Thread ThreadTwo. Incrementer: 14
Thread ThreadOne. Incrementer: 15
Thread ThreadTwo. Incrementer: 16
Thread ThreadOne. Incrementer: 17
Thread ThreadTwo. Incrementer: 18
Thread ThreadOne. Incrementer: 19
Thread ThreadTwo. Incrementer: 20
Using LocksA Example: public void Incrementer( )
{
try
{
while (counter < 1000)
{
lock (this)
{
int temp = counter;
temp ++;
Thread.Sleep(1);
counter = temp;
}
// assign the decremented value
// and display the results
Console.WriteLine("Thread {0}. Incrementer: {1}",
Thread.CurrentThread.Name, counter);
}
}
Using MonitorThere are situations where the programmer need to monitor the running threads, for which we can use the following: Monitor.Enter(this);
Race Condition and DeadlocksThere are situations when the process goes for a deadlock situation. Synchronization is a little tricky to handle in such cases. Race Conditions
DeadlocksIn situations when one thread is dependent on another thread's completion, it is some times possible that unknowingly one thread can wait for the other to finish, so the second thread can go ahead and run the second process. In few occasions, each thread may go in a loop to wait for the next thread to complete the processing to start, where both the threads are waiting for each other to complete and none of them is actually doing any processing.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||