How to work with threads in C#

Thread states

Thread states

Take advantage of threads to implement multithreading and perform several tasks simultaneously to increase the application's throughput

RELATED TOPICS

A thread is the smallest unit of execution within a process. Multithreading is the ability to have multiple threads in memory at a given time and switch amongst them so as to provide a pseudo parallelism, as though all the threads are executing at the same time. Microsoft .Net framework provides excellent support for working with threads.

Programming threads in C#

To work with threads, you should include the System.Threading namespace in your code. To create a new thread, you should leverage the ThreadStart delegate and pass the reference to a method that should execute on the thread. Note that a delegate is a type safe function pointer. The following code snippet shows you can create a new thread object using this delegate.

Thread t = new Thread(new ThreadStart(MyThreadMethod));

To start the newly created thread, you should call the Start method on the thread object you have created. The following code listing illustrates this. Note that the thread method MyThreadMethod executes on the new thread (worker thread) that has been created.

 static void Main()

        {

            Thread t = new Thread(new ThreadStart(MyThreadMethod));

            t.Start();           

            Console.Read();

        }

        static void MyThreadMethod()

        {

            Console.WriteLine("Hello World!");

        }

Thread states

A thread in memory can be in different states -- Aborted, Background, Running, Suspended, UnStarted, etc. Thread states are defined in the ThreadState enumeration available in the System.Threading namespace. Unless the Start method is called on a thread, the thread is in a UnStarted state. When the Start method is invoked on the thread instance, the thread’s state changes from UnStarted to Running.

The following code snippet shows how you can display the state of a thread in the console.

Thread t = new Thread(new ThreadStart(MyThreadMethod));

t.Start();

Console.WriteLine("The thread's state is: " + t.ThreadState.ToString());

Foreground and background threads

Threads can be either foreground or background, i.e., they can run either in the foreground or in the background. The threads that you create explicitly are foreground threads. One of the major differences between a foreground thread and a background thread is that your application would stay alive as long as one or more foreground threads are alive. In essence, the foreground threads prevent the current application from being terminated. On the contrary, background threads don't keep the CLR environment alive.

You can set the background status of a thread using the IsBackground property. Here's a code example that shows how this can be achieved.

static void Main()

        {

            Thread t = new Thread(new ThreadStart(MyThreadMethod));

            t.Start();

            t.IsBackground = true;

            Console.WriteLine("The thread's background status is: "+t.IsBackground.ToString());

            Console.Read();

        }

You can suspend or resume a thread by invoking the Suspend() and Resume() methods respectively on the thread object. Note that you can only resume a thread that was suspended by a call to the Suspend() method.

Thread t = new Thread(new ThreadStart(MyThreadMethod));

t.Start();

t.Suspend(); //Suspends the newly created thread

t.Resume(); //Resumes the suspended thread

However, it should be noted that both of these methods Thread.Suspend() and Thread.Resume() have been deprecated and you would need to achieve the same results by using AutoResetEvent EventWaitHandle.

Thread priority

You can also control a thread's priority tho determine the relative share of time that a thread would get compared to the other threads residing in the memory. Thread priority is defined in the ThreadPriority enumeration and the possible values include: Lowest, BelowNormal, Normal, AboveNormal and Highest. The following code snippet illustrates how you can set the thread priorities of two threads using the Priority property of the thread object.

static void Main()

        {

            Thread thread1 = new Thread(new ThreadStart(Method1));

            Thread thread2 = new Thread(new ThreadStart(Method2));

            thread1.Priority = ThreadPriority.Highest;

            thread2.Priority = ThreadPriority.Lowest;

            thread2.Start();

            thread1.Start();

            Console.Read();

        }

        static void Method1()

        {

            for (int i = 0; i < 10; i++)

            {

                Console.WriteLine("First thread: " + i);

            }

        }

        static void Method2()

        {

            for (int i = 0; i < 10; i++)

            {

                Console.WriteLine("Second thread: " + i);

            }

        }

When you execute the above code snippet, you would observe that the first thread completes its execution ahead of the second thread even though the second thread has been started before the first thread in the Main method.

Threads are expensive as they consume a lot of resources in your system for initialization, switching contexts, and releasing the resources they occupy. Note that multithreading should be used judiciously and only when it is needed. It is always advisable to leverage thread pools to create and manage threads on demand and improve the responsiveness of your application.

This article is published as part of the IDG Contributor Network. Want to Join?

RELATED TOPICS
From CIO: 8 Free Online Courses to Grow Your Tech Skills
View Comments
Join the discussion
Be the first to comment on this article. Our Commenting Policies