Google
WWW Yariv Hammer's Code Site

Friday, March 03, 2006

MultiThreading Without The Thread Class

In this serie of articles I show a lot of the mechanisms we have in .NET to program MultiThreaded applications and to perform asynchronous operations.
Here are the articles in this serie:
Asynchronous Programming in .NET
Synchronizing Threads in .NET
MultiThreading Without The Thread Class

Introduction
In this article I will show several mechanisms of using threads without actually using the Thread class.

Using Timers
There are three types of Timers in the .NET frmawork. System.Windows.Forms.Timer is used in UI forms, and works on Windows messages. This is the least efficient timer.
The System.Timers.Timer and the System.Threading.Timer both work with the Windows timer, and they are quite similar in performance. The System.Timers.Timer is more user-friendly, because it has a Start and Stop methods, an Interval property and so on.

The System.Threading.Timer will invoke a method at a constant rate.
------------------------------------------
public void myMethod(object obj)
{
//Do something
}

public static void Main()
{
Timer t = new Timer(new TimerCallBack(myMethod), anyObject, 0, 1000);
Console.ReadLine();
}
---------------------------------------------
The timer can work on any method that receives an object. The second parameter will be passed to the method as a parameter (pass null if you don't need it). The Thirs argument is how much time (in milliseconds) to wait before starting the timer, and the last parameter is the period of time between to invokations.
The threads are taken out of the Thread Pool, and they run in the background.
When you are done ith the timer, Dispose it.

Using the ThreadPool
If you need to perform a lot of short tasks (a worker thread for example), and then get rid of the threads you can use the ThreadPool to improve performance. When you start your application Windows generates 25 threads for you to use (Actually sometimes, as in timers, the CLR will use threads from the pool). The number of threads in the pool cannot be configured in 2003, so be careful not to use too many threads. If you use a thread from the ThreadPool you save the time of creating and destroying the thread. You just ask for a free thread, and when you are done it goes back to the pool.

Whenever you need to call the QueueUserWorkItem static method to start a thread from the thread pool.
For example:
------------------------------------------
public void myMethod(object obj)
{
//Do something
}

public static void Main()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(myMethod), anyObject);
Console.ReadLine();
}
---------------------------------------------
Like in the timer, you should pass a method that receives an object, and that object as second parameter.
For another example look at MSDN.

Those threads are intended for short actions, that run in the backgroound, with normal priority (you cannot change any of it). You might want to pass a ManualResetEvent as the parameter to the method if you want to be able to synchronize the thread.

Asynchronous Delegates
A reminder about the usage of delegates:
---------------------------------------------------
class Class1
{
public static void f1(int x)
{
for (int i=0; i<x; i++)
{
Console.WriteLine("f1: " + i);
Thread.Sleep(300);
}
}
public delegate void Fptr(int x);
static void Main(string[] args)
{
Fptr p1 = new Fptr(f1);
p1(50);
Console.WriteLine("Main End");
Console.ReadLine();
}
}
----------------------------------------------------
You call the delegate as you call a normal method in order to invoke it. This is called Syncronous Invocations.

Instead we could call the BeginInvoke method of the delegate:
---------------------------------------------------
static void Main(string[] args)
{
Fptr p1 = new Fptr(f1);
p1.BeginInvoke(50,null,null);
Console.WriteLine("Main End");
Console.ReadLine();
}
----------------------------------------------------
You will see that the Main End will ve written as the program starts, to indicate that f1 runs on a different thread. This thread is taken from the Thread Pool.

If we want to return a value from the method f1, we will need to use EndInvoke:
-------------------------------------------------------
public static int f1(int x)
{
for (int i=0; i<x; i++)
{
Console.WriteLine("f1: " + i);
Thread.Sleep(100);
}
return x;
}
public delegate int Fptr(int x);
static void Main(string[] args)
{
Fptr p1 = new Fptr(f1);
IAsyncResult ar = p1.BeginInvoke(50, null, null);
Console.WriteLine("Main Sleeping");
Thread.Sleep(1000);
int res = p1.EndInvoke(ar);
Console.WriteLine("Main End " + res);
Console.ReadLine();
}
------------------------------------------
The method f1 now returns an int. When we call BeginInvoke we are returned with an object of type IAsyncResult. We pass that object to the EndInvoke method and then we wait until the method f1 is done (If it is over when we get to the line we don't wait at all), and we receive the return value. The use of IAsyncResult is because we may start p1 many times, and the EndInvoke should know which time we want to end. The IAsyncResult uniquly identifies the invocation.
Note that EndInvoke blocked the code. A nice propery of IAsyncResult is the IsComplete property which can be called in a loop to know if the method is over (A polling approach).

Another approach might be to receive an event when the method is done. This is the best approach because the code will never be blocked.
For example:
------------------------------------------
public static void f1IsCompleted(IAsyncResult ar)
{
Console.WriteLine("F1 is done");
}
static void Main(string[] args)
{
Fptr p1 = new Fptr(f1);
p1.BeginInvoke(50, new AsyncCallback(f1IsCompleted), null);
Console.WriteLine("Main Sleeping");
Thread.Sleep(1000);
Console.WriteLine("Main End");
Console.ReadLine();
}
--------------------------------------------------------
The method f1IsCompleted receives the IAsyncResult as a parameter. It is called automatically when the f1 method is completed.

The last thing to see is how to retrieve the return value of the method f1. Here is one way to do it:
----------------------------------------------------------
public static void f1IsCompleted(IAsyncResult ar)
{
int res = ((Fptr)ar.AsyncState).EndInvoke(ar);
Console.WriteLine("F1 is done: " + res);
}
static void Main(string[] args)
{
Fptr p1 = new Fptr(f1);
p1.BeginInvoke(50, new AsyncCallback(f1IsCompleted), p1);
Console.WriteLine("Main Sleeping");
Thread.Sleep(1000);
Console.WriteLine("Main End");
Console.ReadLine();
}
-------------------------------------------------
The last parameter of BeginInvoke can be any object. This object can be retrieved as the IAsyncResult.ASyncState property in the callback method. We use this mechanism to pass the delegate, in order to call the EndInvoke after the callback is raised.
Another way to do it was to place the Fptr p1 as a member of the class, so the f1IsCompleted method can access it.

Using Threads With User Interface
Here is a rule: Never access the GUI from any thread other than the GUI thread.
Lets have an axample: We have a form with a ListBox and a Button. We write the following Click event handler for the Button:
---------------------------------------------------
private void button1_Click(object sender, EventArgs e)
{
for (int i=0; i<10000 ; i++)
listBox1.Items.Add(i);
}
-------------------------------------------------
If you run the program and press the button you will see that the form gets stuck until the ListBox is filled with numbers. You might even get a (not responding) in the title of the form.
The reason for this is that if you perform a long task in the event handlers of the form, you are performing it in the GUI thread. No Windows messages can be handled when the GUI thread is working on something else. For that reason you should only perform short taskd in event handlers. Long tasks should be performed in different threads.

Lets look at the following fix:
---------------------------------------------------
private void GenerateNumbers()
{
for (int i=0; i<10000 ; i++)
listBox1.Items.Add(i);
}

private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(GenerateNumbers));
t.Start();
}
-------------------------------------------------
If you run the program and press on the button you get a respons from the form while the ListBox is filled.
You should never do it this way!!! We are accessing the GUI from different thread. In 2005 you will even get an exception.

The correct way of doing this is by calling the Invoke method of the form. This will call a method in the GUI thread:
---------------------------------------------------
private void GenerateNumbers()
{
for (int i=0; i<10000 ; i++)
{
this.Invoke(new Fptr(InsertNumberToList), new object[] {i});
Thread.Sleep(10);
}
}
public delegate void Fptr(int n);
private void InsertNumberToList(int n)
{
listBox1.Items.Add(i);
}
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(GenerateNumbers));
t.Start();
}
-------------------------------------------------
The Invoke method receives a delegate (any delegate) and an array of parameters to pass to the delegate. We are guaranteed that the method will be executed in the GUI thread. However, without the Sleep call the GUI would be frozen, because the loop constantly updates the GUI. The Sleep will make sure that the user gets enough time to interact with the form while the loop is running.

If you run the program you will notice that the ListBox is updating much slower than before. The Sleep we placed is the cause of that. This is the tradeoff we get by performing long tasks which interacts with the UI: Good response from the UI vs. Time it takes to complete the task.

By the way, this method is useful while updating ProgressBars from worker threads.

In 2005 we have a BackGroundWorker control that we can drag to the component tray of the form. This control can manage tasks in backgorund threads for us in a much more user-friendly way.

Summary
In this article I showed how to perform asyncronous operations in a MultiThreaded environment without actually using the Thread class. I showed how to use timers, how to call asyncronous delegates, how to call Invoke in UI applications, and how to use the ThreadPool.

Synchronizing Threads in .NET

In this serie of articles I show a lot of the mechanisms we have in .NET to program MultiThreaded applications and to perform asynchronous operations.
Here are the articles in this serie:
Asynchronous Programming in .NET
Synchronizing Threads in .NET
MultiThreading Without The Thread Class

Introduction
In my previous article I showed how to start and control a thread. In this article I will show how to synchronize threads.

Thread Local Storage
Lets look at the following example:
---------------------------------------
class A
{
public void f1()
{
Delay = 300;
for (int i=0; i<10; i++)
{
Console.WriteLine("f1: " + Delay);
Thread.Sleep(Delay);
}
}
public void f2()
{
Delay = 500;
for (int i=0; i<10; i++)
{
Console.WriteLine("f2: " + Delay);
Thread.Sleep(Delay);
}
}
public static int Delay = 500;
}
class Class1
{
static void Main(string[] args)
{
A a = new A();
Thread t1 = new Thread(new ThreadStart(a.f1));
Thread t2 = new Thread(new ThreadStart(a.f2));
t1.Start();
t2.Start();
Thread.Sleep(1000);
Console.WriteLine("Main End");
}
}
-------------------------------------------------
Delay is a static member of A. If you will run this you will see that the last thread to change Delay will change it both for f1 and f2. The thing is that both threads share the same member, and the last one to change it wins it all.

What we want really is to have one Delay for the first thread, and another Delay for the second thread. There is a built-in mechanism for that in Win32 called Thread Local Storage, and the way to do it in .NET is by using the [ThreadStatic] attribute before declaring the static member.
[ThreadStatic] public static int Delay = 500;

As you can see we initialized the Delay member with a value. This initialization only applies to the main thread. Each thread must set a value in the entry point method, or the value will be 0.
If you run the program now you will see that each thread has its own delay.

Synchronization Mechanisms
Two threads want to access the same variable, or the same code. Context switches can occur at any time, so if the context switch occur in a critical point, the threads can cause unexpected results. An example could be when a thread tries to decrease a variable by one, so it places it in a register, and at that point a context switch occur, another thread decreases the variable, if a context switch occurs again the variable will be decreased only once instead of twich.

There are declerative ways and coding ways to perform synchronization in .NET.
The WaitHandle class is an abstract class which provides a way to signal other threads. Three classes derive from the WaitHandle class: ManualResetEvent, AutoResetEvent and Mutex.
The AutoResetEvent class involves cases in which we want to make sure that threads will sleep until another thread finishes a task. It has two states: Set and Reset. The Set state is signalling one thread to stop waiting, and then automatically goes back to Reset state. A thread can call the WaitOne method of the AutoResetEvent object, and then it is blocked until someone calls the Set method.
Here is an example.

The ManualResetEvent is similar to AutoResetEvent. When a threads wants to block all other threads it calls the Reset method. If any other thread calls the WaitOne it will be blocked until someone calls the Set method. All the threads will be released, and the state will remain Set, until someone sets the state again to Reset.

The Mutex class is used when we want to protect a resource or a critical code. We call the WaitOne at the beginning of the section, and the ReleaseMutex at the end of the section. If one thread called the WaitOne method, other threads will be blocked on that line until the thread calls the ReleaseMutex class. You should perform the ReleaseMutex operation in the finally clause. For a short and nice example look at MSDN .
In 2005 a Semaphore class was added to the framework. There are also named mutexes, and there is an Access Control List feature.

Race Conditions
The class Interlocked provides methods to perform operations as atomic. This will prevent race conditions between threads on variables. In the 2003 version this class provides Increment, Decrement,Exchange (switches two variables), and CompareExchange. In the 2005 version other features were added.

Using Attributes to Synchronize Classes
A class that derives from ContextBoundObject (such as ServicedComponent) can be assigned with the [Synchronization] attribute. No more than one thread will be able to access the class methods and properties. This will not block static methods and members. This is a very easy but strict mechanism. It is not suitable in many cases, for example when there is a Read and Write method. Only one thread can access the Write method, but few threads can access the Read method. This will not work with this attribute.
The class is in the System.Runtime.Remoting.Contexts namespace.

There is a way to protect a method from getting accessed bymore than one thread. Add the following attribute to the method [MethodImpl(MethodImplOptions.Synchronized)].

Locks
C# has a built-in locking mechanism. The lock is per object, so if you want to prevent two threads from executing critical sections together, they should lock on the same object:
---------------------------------------------

public void f1()
{
lock(x)
{
for (int i=0; i<10; i++)
{
Console.WriteLine("f1: " + i);
Thread.Sleep(300);
}
}
}
public void f2()
{
lock(x)
{
for (int i=0; i<10; i++)
{
Console.WriteLine("f2: " + i);
Thread.Sleep(500);
}
}
}
object x = new object();
--------------------------------------------
Only one method can perform the loop at the same time. The ither thread will have to wait until the lock is freed. You can lock on any type of object.

Behind the scenes .NET uses the class Monitor.
If you want to lock a critical section in the context of the object, you can do lock(this).
This will prevent two threads from accessing the critical section only when accessing the same object.

If you want to lock a section in a static method, you might use lock(typeof(MyClass)) .

A nice class to perform read and write operations is the ReaderWriterLock, which lets aquiring a number of reader locks, and only one writer lock.

Summary
In this article I showed a number of ways to synchronize threads using Locks, Mutex, Manual/AutoResetEvent, and attributes. I also showed how to use the Thread Local Storage.

In the next article I will discuss timers, ThreadPool, and Asynchronous delegates.

Thursday, March 02, 2006

Asynchronous Programming in .NET

In this serie of articles I show a lot of the mechanisms we have in .NET to program MultiThreaded applications and to perform asynchronous operations.
Here are the articles in this serie:
Asynchronous Programming in .NET
Synchronizing Threads in .NET
MultiThreading Without The Thread Class

Introduction
Here are four important classes regrading the mangement of processes and threads in the operating system:
- AppDomain - A class that represent a .NET process, in the context of the CLR. Each .NET application is opened as an AppDomain, and later on can open several other AppDomains.
- Thread - A class that represents a managed thread.
- Process - A class in the System.Diagnostics namespace that represents the process from the Win32 point of view. It is mainly for monitoring process information.
- ProcessThread - A class that represents a thread from Win32 point of view, and is used to monitor thread information.
Each .NET application starts 9 thread normally on startup. Only one of them is the managed thread where your code runs. A .NET thread is a Win32 thread, but the other way is not true always. The following line will show you the exact number of threads in your application:
Console.WriteLine(Process.GetCurrentProcess().Threads.Count)
You use the Process class in order to start new processes (by calling the Start method) or to receive information about other processes. The Threads property return a collection of ProcessThread objects. The mthod EnterDebugMode for example can perform the same operation as the TaskManager. ProcessThread for example can set the Processor Affinity.

AppDomain contains several properties regarding the .NET running assembly, and enables to communicate between several AppDomains. We use AppDomains when we want to wrap the environment with security. It is a virtual environment to which we load assemblies and run them. We do not need to worry about releasing resources on exit (The CLR takes care of that for us). We pay with performance of copying data between the AppDomains.

The Thread Class
The Thread class contains static and member methods. We use it when we want to do things in parallel or asynchronously. The threads, unlike AppDomains, share a memory space and resources. Each thread has an entry point, which is a method without parameters which returns no value.
Here is a small example to demonstrate:
---------------------------------------------------
class A
{
public void f1()
{
for (int i=0; i<10;i++)
{
Console.WriteLine("f1: " + i);
Thread.Sleep(500);
}
}
public static void f2()
{
for (int i=0; i<10; i++)
{
Console.WriteLine("f2: " + i);
Thread.Sleep(700);
}
}
}
class Class1
{
static void Main(string[] args)
{
Thread t1 = new Thread(new ThreadStart(A.f2));
A a = new A();
Thread t2 = new Thread(new ThreadStart(a.f1));
t1.Start();
t2.Start();
Console.WriteLine("Main End");
//Console.ReadLine();
}
}

--------------------------------------------------
We have three threads opened: t1, t2 and main. The output starts with the "Main End" message, because the t1 and t2 threads runs in parallel to the main method. The Thread.Sleep method applies to the current thread, and stops the thread for a while. The ThreadStart is a delegate to a void method without parameters. (In 2005 there is an option to pass an object). The thread can have a priority, Which is one of 5 levels. Normal is the defaut.

BackGround Threads
The application will not finish until all threads are over. If you wish the application to end when the main thread is over, you should set the IsBackGround property of the thread to be true:
--------------------------------------------
static void Main(string[] args)
{
Thread t1 = new Thread(new ThreadStart(A.f2));
A a = new A();
Thread t2 = new Thread(new ThreadStart(a.f1));
t1.IsBackGround = true;
t2.IsBackGround = true;
t1.Start();
t2.Start();
Console.WriteLine("Main End");
}
--------------------------------------------
The main method will stop right away, and with it the whole application.

Join
We can use the Join method in order to wait for the thread to end:
--------------------------------------------
static void Main(string[] args)
{
Thread t1 = new Thread(new ThreadStart(A.f2));
A a = new A();
Thread t2 = new Thread(new ThreadStart(a.f1));
t1.Start();
t2.Start();
t1.Join(); // Don't continue until t1 is done
Console.WriteLine("Main End");
}
--------------------------------------------
We can pass an timeout parameter to the Join method. This way we can avoid deadlocks. This overload also return the success status of the thread.

Passing Parameters
When we wish to pass a parameter to a thread we need to add a variable which is shared by the caller and the thread:
--------------------------------------------
class A
{
public int Delay = 500;
public void f1()
{
for (int i=0; i<10; i++)
{
Console.WriteLine("f1: " + i);
Thread.Sleep(Delay);
}
}
}
class Class1
{
static void Main(string[] args)
{
A a = new A();
a.Delay = 1000;
Thread t2 = new Thread(new ThreadStart(a.f1));
t2.Start();
Console.WriteLine("Main End");
}
}
--------------------------------------------
In the example above we passed the Delay variable to the thread. We can use any variable that is acessible to the thread in order to pass parameters to the thread.

Changing Thread State
The Abort method will recommend for the thread to stop by throwing an exception in the thread.
--------------------------------------------
static void Main(string[] args)
{
Thread t1 = new Thread(new ThreadStart(A.f2));
A a = new A();
a.Delay = 1000;
Thread t2 = new Thread(new ThreadStart(a.f1));
t1.Start();
t2.Start();
Thread.Sleep(1000);
t1.Abort();
Console.WriteLine("Main End");
}
--------------------------------------------
Only the t2 thread will finish gracefully.

The Interrupt method, similar to the Abort method, throws an exception to the thread. The only difference is that after the thread handles the exception it continues to work.

In both cases the exception is asynchronous (you cannot deterministically determin the exact time the thread will catch the exception). You can pass an object (StateInfo) to the exception, and the thread can use it if necessary. Here is how you catch the event in the thread:
--------------------------------------------
public void f1()
{
try
{
// Do stuff here
}
catch (ThreadAbortException ex)
{
// you can use ex.ExceptionState in order to get the object passed in the Abort method.
}
finally
{
}
}
-----------------------------------------------------
If in the catch clause we write Thread.ResetAbort() we can bypass the Abort command and cancel the abort (in Interrupt we have it automatically).

It is not recommended to stop a thread by using Abort if the thread handles resources. The problem is that the exception can be caught at any time, and if it were cought in the finally clause, the exception will not be handled at all, and the thread will be stopped without freeing the resources.

A solution to this problem could be to use a public volatile member flag in the object, which is checked by the thread, and when set to true, the thread exits gracefully:
---------------------------------------
class A
{
public volatile bool ThreadStop = false;
public int Delay = 500;
public void f1()
{
for (int i=0; i<10; i++)
{
if (ThreadStop)
return;
Console.WriteLine("f1: " + i);
Thread.Sleep(Delay);
}
}
}

class Class1
{
static void Main(string[] args)
{
A a = new A();
a.Delay = 1000;
Thread t2 = new Thread(new ThreadStart(a.f1));
t2.Start();
Thread.Sleep(1000);
a.ThreadStop = true;
Console.WriteLine("Main End");
}
}
----------------------------------------
We use a volatile member in order to instruct the garbage colector not to do any optimizations on this member, and to pass it to a register. This will make sure that a concurrent method that wants to stop the thread will not have a context switch problem when registered are restored.

Suspend and Resume can help external threads to control the state execution status.

Appartment State
If you want call a COM component from the thread you should know whether it runs in a Multi Threaded Appartment (MTA) or Single Stated Apartment (STA). The Thread class has an ApartmentState property, that you can set to MTA (default) or STA. If the COM and the thread appartment state do not match you might get performance issues (because of extra marshaling between apartments).
You might have noticed that the automated Main method has an attribute called [STAThread]. This means that the main thread will always work with STA appartments. The question that comes to mind is why not just write "Thread.CurrentThread.ApartmentState = ApartmentState.STA;" in the first line of Main. The answer is that the Main is not the first command the application does. There are many operations that happen when the application loads before Main is called, and in these operations there might have been calls to COM.

Summary
In this article I introduced some classes in .NET that represents units of run-time environment in the CLR and in Win32. I covered some of the capabilities of the Thread class. I showed how to run threads in the background, how to wait for a thread to end, how to make a thread sleep, and how to tell a thread to end.
In the next article I will discuss other issues regarding threads.

Feel free to use everything here. Add links to my site if you wish.

Do not copy anything to other sites without adding link to here.

All the contents of the site belong to Yariv Hammer.