Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Understanding Traditional Threading in C#

0.00/5 (No votes)
17 Feb 2014 1  
Here I will discuss the concepts of threading / multi-threading in C# using program.

Introduction

Here I will discuss the concepts of threading / multi-threading in C# using program. I would recommend that you should copy the given programs in your Visual Studio and run the program after making changes as you wish to see its impact. For example, if you have doubts about whether a method invoked by thread can return some value or not, just modify the return type of the method accordingly. Compile, run the program. You will get your answers while compiling or running the program. It will help you not only to understand the concepts but remember as well.

using System;

namespace TestConsole
{
    class Program
    {
        public static void Main(string[] args)
        {
            var traditionalThread = new TraditionalThread();
            traditionalThread.TestTraditionalThreadWithoutParameters();
            traditionalThread.TestTraditionalThreadWithParameters();
            Console.ReadKey();
        }
    }
}
using System;
using System.Collections.Generic;
using System.Threading;

namespace TestConsole
{
    public class TraditionalThread
    {
        public void TestTraditionalThreadWithoutParameters()
        {
            Console.WriteLine("Testing threads with methods not having parameter");
            var threads = new List<Thread>
                              {
                                  new Thread(PrintNumbers),
                                  new Thread(new ThreadStart
                                  (PrintNumbers)), //Use ThreadStart when method has no parameter
                                  new Thread(PrintNumbers),
                                  new Thread(() => Console.WriteLine
                                  ("You can use lambda expression or anonymous methods as well"))
                              };
            threads.ForEach(t => t.Start()); //Start all the threads
            threads.ForEach(t => t.Join()); //If you omit this line, program will exit 
            		// without completing PrintNumbers since main thread will not wait.
        }

        public void TestTraditionalThreadWithParameters()
        {
            Console.WriteLine("Testing threads with methods having parameter");
            var threads = new List<Thread>
                              {
                                  new Thread(new ParameterizedThreadStart
                                  (PrintParticularCharacter)), //User 
                                  // ParameterizedThreadStart when method has parameter
                                  new Thread((toPrint) =>
                                                 {
                                                     for (var count = 0; count < 10; count++)
                                                         Console.WriteLine("ThreadId : {0}  and Value : {1}",
                                                            Thread.CurrentThread.ManagedThreadId, toPrint);
                                                 })
                              };
            threads[0].Start("X");
            threads[1].Start("Y");
            threads.ForEach(t => t.Join()); //If you omit this line, 
            // program will exit without completing PrintNumbers since main thread will not wait.
        }

        private static void PrintNumbers() //Must return void if invoked by thread using ThreadStart
        {
            for (var count = 0; count < 10; count++)
            {
                Console.WriteLine("ThreadId : {0} 
                	and Value : {1}", Thread.CurrentThread.ManagedThreadId, count);
                Thread.Sleep(1000); //Sleep for 1 sec. It will not consume CPU cycle.
            }
        }

        private static void PrintParticularCharacter(object toPrint)  //Must return void and 
        	//parameter type must be object if invoked by thread using ParameterizedThreadStart
        {
            for (var count = 0; count < 10; count++)
            {
                Console.WriteLine("ThreadId : {0}  
                	and Value : {1}", Thread.CurrentThread.ManagedThreadId, toPrint);
                Thread.Sleep(1000); //Sleep for 1 sec
            }
        }
    }
}

Below are some terms/concepts you must know.

Thread.Sleep

You can call this method on any thread object. It makes that thread sleep for a given time period. It accepts time period in milliseconds. It does not consume CPU cycles while sleeping.

Example
t1.sleep(1000); // It will make thread t1 to sleep for 1 second.

Thread.Join

You can call this method on any thread object. It makes the parent thread wait for the child thread. The main/parent thread will wait for the child thread to complete.

Example
t1.Join();    //Main thread will wait for thread t1 to complete.
t2.Join(2000);    //Main thread will wait for thread t2 for 2 seconds to complete. 
	// After 2 seconds, main thread will start processing next statements.

Background and Foreground Threads

By default, threads you create explicitly are foreground threads. Foreground threads keep the application alive for as long as any one of them is running, whereas background threads do not. Once all foreground threads finish, the application ends, and any background threads still running abruptly terminate.

You can check if the thread is a background thread or foreground thread by using thread’s property “IsBackground”.

Thread Pooling >>

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here