Page 1 of 5
Threading is a big and important topic. We explain how the many forms of Invoke in C# make it easier and describe the invoke patttern and how you can use it in your own objects.
A thread of execution is just that - a set of instructions that are carried out more or less independently of any other set of instructions.
The simplest and most common programming model is single threading. In .NET every program has a single UI thread of execution which responds to all of the events generated by the user. The majority of programs really don’t need anything more than this single thread of execution but occasionally there is something to be gained in using more than one thread.
Generally speaking multi-threading can make a program more responsive to the user by splitting off worker threads that don’t block the UI thread. Multi-threading can make a program actually run faster – although this is a much less common situation than you might think. The only gains in efficiency that are possible are if a single thread is repeatedly blocked waiting for something to happen and there is work that another thread could be getting on with. In this case however the single threaded version of the program could also be made more efficient by simply getting it to do work while it would otherwise be idle.
Until quite recently most multi-threading was simulated by the operating system switching a single processor’s attention between a set of active threads. In this case there is only one thread actually being obeyed at any one time but the rate of switching between threads is sufficiently high to give the impression that all of the threads are being run. Simulating multi-threading is generally done by pre-emptive multi-tasking, this is certainly how modern versions of Window work, but there are other ways of doing it.
With the rise of multi-core processors the possibility of real multi-threading – albeit limited to a small number of threads – has become possible and in this case the potential for speed increases is more real. All in all threading is becoming increasingly important.
The good news is that .NET makes the creation of multi-threaded programs very easy.
The bad news is that .NET makes the creation of multi-threaded programs very easy.
Using multiple threads properly is a very difficult and subtle task and not to be undertaken lightly. So while it is good that .NET makes it easy this should not be taken as an encouragement to multi-thread without some careful thought. In this article you will discover how multi-threading works but more importantly how it can go very wrong.
In particular we take a look at some of the more obscure ways in which threading can become part of your program via invoke and the background worker class – but first some standard threading.
Starting a thread
There is more than one way that you can enter the world of multi-threaded programs – some of them are so simple that you might not even notice the transition.
For example when you employ of an asynchronous call using BeginInvoke you use a separate thread to run the method without you having to do anything extra. However no matter how you create a new thread the same considerations apply.
There are two ways of explicitly using a thread in your program.
The first is to use one of the existing threads in the thread pool. This has the advantage that you don’t have the overhead of actually creating a new thread but the number of threads available for use in the thread pool is limited. In general you should only use a thread pool thread for tasks that are short so that you can release the thread back to the thread pool as soon as possible. The same concerns apply to using a thread pool thread as one you create yourself.
As long as the task that you want the thread to do is sufficiently long-lived you are advised to create a thread for it. To do this you need to use the Thread class in System.Threading. The Thread constructor accepts either a ThreadStart or a ParameterizedThreadStart delegate which wraps the method that will be executed by the new thread. For example, suppose we have a method like:
public void CountUp()
for (int i = 0; i < 99; i++)
then this can be run as a new thread using:
Thread T1=new Thread(
This creates the new thread object but doesn’t actually start the thread running. To do this we have to use the Start method:
You will now see the messagebox appear and as long as you keep clicking the OK button the thread will continue.
There are a number of thread methods that can be used to stop and pause threads but what these do and how they are used is fairly obvious.
Here we will concentrate on more difficult aspects of threading.