Click here to Skip to main content
Licence CPOL
First Posted 13 May 2010
Views 7,207
Downloads 164
Bookmarked 16 times

Multiple Concurrent Tasks in .NET - Using Threads

By | 13 May 2010 | Article
Two simple ways to get started with threads in .NET

Introduction

Most applications need to perform more than one task at the same time. Whether it is a WinForms control that needs to accept user input and launch a background task while staying responsive - or whether it is a business object that needs to perform simultaneous tasks (e.g. a BackgroundChecker business object which does a BackgroundCreditCheck and a BackgroundCriminalRecordCheck) - multiple concurrent tasks are a key component of most application workflows.

Background

Working with threads in .NET is fairly straightforward. You have two options:

  1. Manually creating new threads (usually for longer running tasks), and
  2. Using .NET’s built-in thread pool (typically for shorter running tasks)

Option 1 - Manually Create Threads

Option 1 - Manually create your own thread (Works for both short-running and long running tasks)

Say you have a method (a long running task) that you want to assign to a new thread. All you need to do is pass in the name of the long running method to ThreadStart. ThreadStart is a built-in .NET class which contains all the necessary plumbing for creating a thread, passing values to the method on the thread, getting notifications back from it, etc. The example below is the simplest possible usage of ThreadStart.

//	Manual Thread Creation in C# 

using System.Threading;
using System.Diagnostics;

namespace ManualThreadCreation
{
    class Program
    { 
        static void Main(string[] args)
        {
                ThreadStart ts = new ThreadStart(LongRunningTask);
                Thread t = new Thread(ts);
                t.Start();
        }
        static void LongRunningTask()
        {
         // ... See Zipped Code in the downloads below
        }
   }
}

Option 2 - Use .NET's Built-in Thread Pool

Say you have more than one task that needs to get done – and each task is fairly short in duration. As an example, consider a given geometric shape for which you need to:

  1. calculate its area (Task 1), and
  2. calculate its volume (Task 2)

Say that you do not want to deal with creating a new thread manually (option 1) – because then you have to worry about correctly disposing of the thread when you are done, you have to worry about the thread inadvertently accessing resources that another thread may be using (concurrency), etc. Since you are a ‘keep it simple’ kind of person, you want to let .NET handle all these threading details for you. All you want to do is to be able to say – Give me a thread – and execute task1 on it, give me another thread and execute task2 on it.

Again, it is important to emphasize that this approach (using the Thread Pool) be used primarily for shorter running tasks. If even one of our tasks was longer running – we would be better off with manually creating threads (Option 1). For example – say your workflow requires a real time background check on a loan applicant. You decide that you can use one thread to perform a ‘personal credit’ check while you use another thread to do a ‘criminal background’ check’. Since each of these tasks could be fairly time consuming, using .NET’s thread pool would not be a good way to go. You would need to resort to method 1 – which involves manually creating the individual threads for each of the long running tasks.

The main components of using .NET’s ThreadPool are shown below (full zipped code available for download below). As one can see, using a ‘ready-to-use’ thread from the thread pool just involves a single line of code – ThreadPool.QueueUserWorkItem. The supporting objects (state and EventWaitHandle) are explained in the full code (see zipped solution download below).

//Use .NET's Thread Pool to create threads
State state1 = new State(new Sphere(radius));

// Task1 - Calculate the area() of the shape (passed in inside the state object)
ThreadPool.QueueUserWorkItem(new WaitCallback(CalculateArea), state1);

// Task2 - Calculate the Volume() of the shape 
State state2 = new State(new Sphere(radius));
ThreadPool.QueueUserWorkItem(new WaitCallback(CalculateVolume), state2);

// WaitOne means - no one else is allowed to use this
// thread till its task (CalculateArea) is done
state1.eventWaitHandle.WaitOne();
// WaitOne means - no one else is allowed to use
// this thread till its task (CalculateVolume) is done
state2.eventWaitHandle.WaitOne(); 

Summary - When to Use (and When Not to Use) .NET's Built-in Thread Pool

Suppose you are faced with executing multiple tasks in parallel. The first question you need to address is ‘Are any of these tasks long-running ?’ If yes, then your best bet is to manually create threads – and avoid .NET’s thread pool altogether. If all your tasks are short-running, then you can either use the ThreadPool or better still – just use a single thread to execute them serially.

History

  • 13th May, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

avarma

Architect
ANUJ Technologies Inc.
United States United States

Member

Anuj Varma is a .NET and SQL Server Architect based in Austin, TX.
 
Specializing in Object Oriented and Component Oriented Development, Anuj leverages leading application frameworks (especially Microsoft's .NET framework) as well as 3rd party components built around these frameworks.
 
Clients include Texas based companies such as DELL and British Petroleum - as well as companies based in New York, California and across the United States.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralMy vote of 2 PinmemberMattia Baldinger19:27 14 May '10  
GeneralMy vote of 1 PinmemberHeywood4:35 14 May '10  
GeneralRe: My vote of 1 Pinmemberavarma5:26 14 May '10  
GeneralNot Adequate PinmemberJohn Simmons / outlaw programmer9:15 13 May '10  
GeneralRe: Not Adequate Pinmemberavarma13:10 13 May '10  
GeneralThe start is ok... PinmemberPaulo Zemek9:03 13 May '10  
GeneralRe: The start is ok... Pinmemberavarma12:51 13 May '10  
GeneralProof before post PinmvpDave Kreskowiak8:32 13 May '10  
GeneralRe: Proof before post Pinmemberavarma13:13 13 May '10  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web02 | 2.5.120517.1 | Last Updated 13 May 2010
Article Copyright 2010 by avarma
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid