Wednesday, February 16, 2005

Using The ThreadPool Class - 2

Using The RegisterWaitForSingleObject() Method:
We cal also queue work items that have wait operations involved with them to the thread pool. The method is defined as such:

public static RegisteredWaitHandle RegisterWaitForSingleObject(
WaitHandle waitObject,
WaitOrTimerCallback callBack,
object state,
int millisecondsTimeOutInterval,
bool executeOnlyOnce);

Example:

class RegWait

{
private static int i = 0;

public static void Main()

{
AutoResetEvent
arev = new AutoResetEvent(false);
ThreadPool.RegisterWaitForSingleObject(arev, new WaitOrTimerCallback(WorkItem), null, 2000, true);
Thread.Sleep(3000);
arev.Set();
Console.ReadKey(false);
}
public static void WorkItem(object o, bool timedOut)
{
Console.WriteLine("Thread Pool Work Item Invoked: " + i++ + "
timedOut = " + timedOut);
while (true)
{
Console.WriteLine("Hello hello");
}
}
}

WaitHandle waitObject
RegisterWaitForSingleObject() takes in a wait handle, for this example we pass it an AutoResetEvent object.

WaitOrTimerCallback callBack
Its second argument is a delegate for WaitOrTimerCallback which has the signature of

public delegate void WaitOrTimerCallback( object state, bool timedOut );

timeOut is true if the WaitHandle timed out; false if it was signaled.

object state
The third argument is the object to be passed to the thread.

int millisecondsTimeOutInterval
This is the amount of time to wait for WaitHandle (amount of time to wait if the current WaitHandle is not signaled) before the WaitOrTimerCallback delegate is called.

bool executeOnlyOnce
True if the WaitOrTimerCallback delegate is executed only once.
False if the WaitOrTimerCallback delegate keeps executing whenever the millisecondsTimeOutInterval expires.

Usage:
The RegisterWaitForSingleObject queues the delegate to the thread pool. The worker thread will only execute the delegate if these two events occur:

(1) The WaitHandle is in the signaled state.
(2) The time-out interval elapses
The RegisterWaitForSingleObject method checks the current state of the specified object's WaitHandle. If the object's state is unsignaled, the method registers a wait operation. The wait operation is performed by a thread from the thread pool. The delegate is executed by a worker thread when the object's state becomes signaled or the time-out interval elapses. If the timeOutInterval parameter is not zero (0) and the executeOnlyOnce parameter is false, the timer is reset every time the event is signaled or the time-out interval elapses.

To cancel the wait operation, call the RegisteredWaitHandle.Unregister method - public bool Unregister(WaitHandle waitObject); [It returns true if the function succeed or false if otherwise) For example:

RegisteredWaitHandle wHandle = ThreadPool.RegisterWaitForSingleObject(
arev, new WaitOrTimerCallback(WorkItem), null, 500, false);


To cancel the wait operation, call wHandle.Unregister(arev)

Using The ThreadPool Class - 1

Rules:

(1) There can only be one ThreadPool object per application.
What this means is when the application quits, the threads in the threadpool gets destroyed as well. (They don't run in the background).

(2)The ThreadPool object is created for the first time when we call the ThreadPool.QueueUserWorkItem() method (or when a callback method is called)

Example:

public class ThreadPoolDemo


{
public void LongTask1(object obj)
{
for (int i = 0; i <= 99; i++)
Console.WriteLine("Long Task 1 is being executed");
}

public void LongTask2(object obj)
{
for (int i = 0; i <= 99; i++)
Console.WriteLine("Long Task 2 is being executed");
}

public static void Main(string[] args)
{
ThreadPoolDemo tpd = new ThreadPoolDemo();
for (int i = 0; i < 5; i++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(tpd.LongTask1));
ThreadPool.QueueUserWorkItem(new WaitCallback(tpd.LongTask2));
}
Console.ReadKey(false);
}
Case 1: No passing of object
The method to use to start a threadpool is the static method ThreadPool.QueueUserWorkItem(). This method has two overloaded version. The first one (as shown in the above example) takes in a WaitCallBack delegate. The signature of the delegate is


public delegate void WaitCallback( object state );
Therefore a worker method to be used in a threadpool must have a return value of void and an object for argument).

Usage:
ThreadPool.QueueUserWorkItem(new WaitCallback(tpd.LongTask1));

Case 2: Pass One Object
You can use an object to encapsulate all the input and output parameters to be passed to a thread in the threadpool. The signature of the overloaded QueueUserWorkItem() is


public static bool QueueUserWorkItem( WaitCallback callBack, object state );


Usage:
ThreadPool.QueueUserWorkItem(new WaitCallback(tpd.LongTask1), stateObject);

Sunday, February 13, 2005

AutoResetEvent Class

The AutoResetEvent class behaves exactly the same as its ManualResetEvent counterpart, except that the call to WaitOne() will (as its name implies) automatically reset the state of the AutoResetEvent object (making it non-signaled – false)

ManualResetEvent Class

ManualResetEvent Class
A ManualResetEvent object can posses either one of the two states – signaled (true) or non-signaled (false).

Constructor
Takes in a parameter that affirms the initial state of the object (whether it is signaled or non-signaled).

Usage
ManualResetEvent mansig = new ManualResetEvent(false);

This will create a ManualResetEvent object mansig whose initial state is non-signaled.

bool WaitOne(int32 timeOutMiliseconds, bool exitContext)
When a WaitOne() method is called, it will block (wait) until mansig is signaled (true) or a time value expire. It takes two parameters, the first one is the milliseconds to wait before expiring, and the second boolean parameter to indicate whether we are already in a synchronization domain and want to exit the synchronization context (if you want to reacquire the synchronization context, the exitContext parameter should be set to true). Usually, it is set to false. It returns true if the WaitOne() receives a signal and false if it timeouts. Example,

bool b = mansig.WaitOne(1000, false);

If mansig was defined as above, b will have the value false (because the state of ManualResetEvent is still false) and this WaitOne method call will block for 1 second before returning.

If we change the initial state of the ManualResetEvent to signaled, then the thread does not wait at the WaitOne() method even if a timeout value is specified.

public bool Reset();
To change the state of the ManualResetEvent to non-signaled (false), we call the Reset() method.

public bool Set();
To change the state to signaled, we call the Set() method.

Thursday, February 10, 2005

Mutex - 1

Mutex
Mutex are like Monitors in that they ensure only one thread can execute a given section of the code between the (assumming that a Mutex object has been created called MutexObject) MutexObject.WaitOne() and MutexObject.ReleaseMutex() .

The default mutex constructor will create a mutex that isn’t owned by the calling thread. That means it is signalled and any thread that has the MutexObject.WaitOne() will not block.

If the mutex constructor is passed a (true) argument, then the calling thread has ownership and All the other thread that is waiting (MutexObject.WaitOne() ) on the mutex will be blocked. They can be unblocked only when the calling thread calls MutexObject.ReleaseMutex().

When the MutexObject.WaitOne() is called, it waits on the MutexObject if it doesn’t own the mutex. i.e., if the MutexObject is not owned, then the call is blocked. Otherwise, the call to MutexObject.WaitOne() gets through.

When the thread that owns the MutexObject wants to release its ownership (i.e. allows other threads that are waiting on the MutexObject) it calls the MutexObject.ReleaseMutex() method. Care must be ensured that only the owning thread can call the ReleaseMutex() method, otherwise an ApplicationException exception will be thrown.

Mutex - 2

Mutex (with name)
Named Mutex works across applications. A named Mutex is created by its overloaded constructor
public Mutex(bool initiallyOwned , string name)
The first argument specifies whether the calling thread receives the initial ownership of the Mutex.

The second string argument is the name for this mutex. “If name is not null and initiallyOwned is true, then the application must ensure that a mutex (that has the same name and is owned by the calling thread) does not already exist. If the mutex is being used for cross-process communication, you should set initiallyOwned to false, or use the Mutex(Boolean, String, Boolean) constructor. Otherwise, it will be difficult to determine which process has initial ownership.” (from MSDN “Mutex Constructor (Boolean, String)” )


The below code shows a great way how mutex can be used:


using System;
using System.Threading;
public class TestMutex

{
public static void Main()
{
// Create the named mutex. Only one system object named
// "MyMutex" can exist; the local Mutex object represents
// this system object, regardless of which process or thread
// caused "MyMutex" to be created.

Mutex m = new Mutex(false, "MyMutex");
// Try to gain control of the named mutex. If the mutex is
// controlled by another thread, wait for it to be released.

Console.WriteLine("Waiting for the Mutex.");
m.WaitOne();
// Keep control of the mutex until the user presses
// ENTER.

Console.WriteLine("This application owns the mutex. " + "Press ENTER to release the mutex and exit.");
Console.ReadLine();
m.ReleaseMutex();
}

}
// This example shows how a named mutex is used to signal between
// processes or threads.
// Run this program from two (or more) command windows. Each process
// creates a Mutex object that represents the named mutex "MyMutex".
// The named mutex is a system object whose lifetime is bounded by the
// lifetimes of the Mutex objects that represent it. The named mutex
// is created when the first process creates its local Mutex; in this
// example, the named mutex is owned by the first process. The named
// mutex is destroyed when all the Mutex objects that represent it
// have been released.
// The constructor overload shown here cannot tell the calling thread
// whether initial ownership of the named mutex was granted. Therefore,
// do not request initial ownership unless you are certain that the
// thread will create the named mutex.

ReaderWriterLock Class

ReaderWriterLock Class
This class implements a single-writer but multiple-reader semantics. Think of a file operations where only one and only one thread can write (make changes) to a particular file but the rest can only read. The four main methods in the class are:

(1) AcquireReaderLock() – It acquires a reader lock. It accepts an argument (integer or a TimeSpan) for timeout value.

(2) AcquireWriterLock() – This acquires a writer block. It accepts an argument (integer or a TimeSpan) for timeout value.

(3) ReleaseReaderLock() – Releases the reader lock.

(4) ReleaseWriterLock() – Release the writer lock.

Reader threads can acquire a lock only if there are no writers holding the lock.
Writer threads can acquire lock only if there are no readers or writers holding the lock.
Only Reader threads can have concurruent access to the object after acquiring the reader lock.

Monitor Class

Monitor
Monitors are used to synchronize sections of code by acquiring a lock with the method. One thread gets the lock, while others wait until the lock is released. Once the lock is acquired on a code region, we can use the following methods between the Monitor.Enter() and Monitor.Exit() block.

Wait() – This method releases the lock on an object and blocks the current thread until it reacquires the lock.

Pulse() – This method notifies a thread that is waiting in a queue that there has been a change in the object's state.

PulseAll() – This method notifies all threads that are waiting in a queue that there has been a change in the object’s state.

Enter() and Exit() Methods
The Monitor methods are static and can be called on the Monitor class itself. Each object in the .NET framework has a lock associated with it that can be obtained and released so that only one thread at any time can access the object’s instance variable and methods. The .NET framework also provides a mechanism that allows it to be in a waiting state – the main reason for this mechanism is to aid aommunication between threads. Such mechanism arises when one thread enters the critical section of an object and needs a certain condition to exist and assumes that another thread will create that condition from the same critical section.

Wait – and – Pulse Mechanism
The question arises as to how this can be done. If only one thread is allowed in a critical section at any one point of time – when the first thread arrives at the critical section, no other threads can. So how will the second thread create a condition in the critical section when the first thread is already in it? This is how – If for example thread A has to get some data from the database and antoher thread (B) has to wait until all the data is received and then process the data. Thread B will enter the critical section and class the Wait() method and waits for thread A to notify it when the data arrives. When the data does arrives, A calls the Pulse() method, which notifies B so that B can process the data. This is the Wait and Pulse mechanism.

(i) The first thread enters the critical section and executes the Wait() method.
(ii) The Wait() method releases the lock prior to waiting.
(iii) The second thread is now allowed to enter the critical section, changes the requird condition, and calls the Pulse() method to notify the waiting thread that the condition has been reached and it can now continue its execution.
(iv) The first thread then reacquires the lock prior to returning from the Monitor.Wait() method and continues execution form the point where it called Monitor.Wait().

No two threads can enter the Enter() method simultaneously.

Wait() and Pulse() Mechanism
They are used for interaction between threads. When a Wait() method is issued on a object, the thread that is accessing that object waits until it gets a signal to wake up. Pulse() and PulseAll() are used for signaling to waiting threads.

Wait() and Pulse() methods can only be called within the Enter() and Exit() code block.

TryEnter() Method
The TryEnter() method of the Monitor class is similar to the Enter() method in that it tries to acquire an exclusive lock on an object. But it does not block like the Enter() method. If the thread enters successfully then the TryEnter() method returns true.

Tuesday, February 08, 2005

Synchronization in .NET

The MethodImplAttribute Class

System.Runtime.CompilerServices namespace contains attributes that affect the runtime behaviour of the CLR. MethodImplAttribute notifies the CLR on how the method is implemented. One of its constructors accesp the MethodImplOptions enumeration as a parameter. The MethodImplOptions enumeration has a field named Synchronized that specifies that only one thread is allowed to access this method at any one time.

This is done by doing this:
[MethodImpl(MethodImplOptions.Synchronized)]
public void doThis() { ... }




Make an Object Thread-Safe - 1

(1) Synchronize critical sections within the code

Restrict access to that resource such that only one thread can update the resource at any point of time -- make it thread safe.

To do that we must identify and synchronize its critical sections. A critical sectoin is piece of code in the program that may be accessed by multiple threads at the same time to update the state of the object. Let’s say we have a method Withdraw() and it will be accessed from many threads, we need to make WIthdraw() method thread-safe. We do that by synchronize the Withdraw() method so that only one thread can access it at any one time.

Lines of code (statements) that cannot be interrupted during its execution is said to be atomic. An atomic process are unitse of code that execute as one complete unit -- as if they were a single statement. By making Withdraw() method atomic, no other thread can call it until the calling thread has finished executing Withdraw().

(2) Make the object immutable

An immutable object is one whose state can’t be changed once the object has been created. The critical sections that change the instance variable of the object are changed so that, instead of changing the state of the current object, a new object is created that embodies the new state and a reference to that new object is returned. In this way, there is no need to lock the the critical section because no methods of an immutable object actually writes to the object’s instance variable.

(3) Use a thread-safe wrapper

In this strategy, a thread-safe wrapper class is written over the object that will be thread-safe, rather than making the object thread-safe. THe object will remain unchanged and the new wrapper class will contain synchronized sections of thread-safe code.

Wednesday, February 02, 2005

Interrupting a Thread

When a thread is in the sleep mode, it goes to the WaitSleepJoin state.

The only way for that thread to “wake up” before its timeout expiures is to use the Interrupt() method.

When a calling thread interrupts a sleeping threat, a ThreadInterruptedException is thrown in the interrupted thread.

This is a sample code from Microsoft's MSDN


while (!sleepSwitch)
   {
   // Use SpinWait instead of Sleep to demonstrate the
   // effect of calling Interrupt on a running thread.
   Thread.SpinWait(10000000);
   }
try
   {
   Console.WriteLine("newThread going to sleep.");
   // When newThread goes to sleep (blocks),
   // it is immediately
   // woken up by a ThreadInterruptedException.
   Thread.Sleep(TimeSpan.FromMilliseconds(1));
   Console.WriteLine("newThred awaken");
   }
catch (ThreadInterruptedException )
   {
   Console.WriteLine("newThread cannot go to sleep - " +
                     "interrupted by main thread - ");
   }





Put a Thread to Sleep

Thread.Sleep()

Use this method to put a thread to sleep. It comes with two overloaded version.

The first version takes an integer of miliseconds as an argument and will put the thread to sleep for the number of milliseconds specified.

Usage: Thread.Sleep(5000)

The above statement will cause the current thread to sleep for 5 seconds.

The second version takes a TimeSpan argument

Usage: Thread.Sleep(TimeSpan.FromSeconds(5))

The above statement will cause the current thread to sleep for 5 seconds.