C# Explained: Differences between Threads, Thread Pool & Delegates

Introduction

If you are new to multi-threading in C# and Visual Studio then you might find it very easy to use the concept of threading (create threads) to run parallel tasks. But once you start building complicated software, which would require a thread to perform asynchronous work (with/without a return value) while running parallel. This is confusing, Asynchronous & Parallel at the same time?!

Let's take an example: 

If you are developing a software which has two buttons (you can have more....), one of which uses the main thread to perform a task and another one uses a separate thread to perform another task. Therefore these two threads can be run simultaneously (in parallel). But what if one of the tasks require interacting with the other task i.e. work asynchronously with the other task? The visual studio (in debugging mode) will through you an error, 'System.InvalidOperationException': Cross-Threading Operation not valid. Which in simple words says that it can not allow you to update/interact with another task of another thread using the current thread (task). Have a look at this Gallery Code Contribution: Cross-Threading Operation and Delegates (Using Control.Invoke Method)  (https://code.msdn.microsoft.com/Cross-Threading-and-18eb841b).

After a brief online search for the solution, the most common solution which you could find is to use Delegates. But once you start digging and become experienced with such applications which require both parallel processing and asynchronous activities, you will find the best way to achieve this is far more complicated to code and design. But this is not completely impossible, just difficult. Have a look at an article by Microsoft: Asynchronous Programming with Async and Await (C# and Visual Basic)which shows how to code asynchronous programs.

As as a beginner when you are starting to code multithreaded software using Threading, Thread Pools & Delegates you may wonder what are the differences between these? Are Threading, Thread Pools & Delegates the same but different ways fusing? Or are these completely different techniques? When and where to use Threading & Delegates concepts properly? If are in doubt then do not worry. This article tries to resolve the confusion based on Threading, Thread Pools & Delegates.

The Start of this thought (article).

See: Difference between Threading and Delegates in C#.net Difference between delegate.BeginInvoke and using ThreadPool threads in C# , etc.

If you do not have clear ideas about when, where and why you should use Threads, Thread Pool & Delegates then it makes it really difficult to build a properly coded multi-threaded software with asynchronous operations. This article tries to provide the differences and usage conditions of these concepts.

Usage of Threads, Thread Pool & Delegates

In brief, 

  • Thread Class should be used when you need the ability to cancel your asynchronous operation. [General Definition: Threading enables your C# program to perform concurrent processing so you can do more than one operation at a time.]
  • Thread Pool Class should be used when you need to schedule asynchronous operation and do not need return value or/and ability to cancel your operation [General Definition: A thread pool is a collection of threads that can be used to perform several tasks in the background. This leaves the primary thread free to perform other tasks asynchronously.]
  • Delegates (using BeginInvoke/EndInvoke) should be used when you need to achieve some return value from your asynchronous operation. [General Definition: A delegate is a type that references a method. Once a delegate is assigned a method, it behaves exactly like that method. The delegate method can be used like any other method, with parameters and a return value.]

To know more

Easy Way to Implement The Techniques

There can be many ways in which Threading, ThreadPooling & Delegates can be implemented (depending on programmers), but in this section few of the popular implementation methods (which seemed very easy to me) are mentioned.

Threading:

Initialize and call the function, which you want to run using a new thread. Example,

Thread MyNewThread = new Thread (MyFunction);  // Kick off a new thread
MyNewThread.Start();  // running MyFunction()

By the way, do not forget to insert (import) the following namespace: 'using System.Threading;'

Also have a look at this easy to understand article: Threading in C#

ThreadPooling:

You can implement ThreadPooling as mentioned in the MSDN article (ThreadPooling) itself:

public void DoWork()
{ 
// Queue a task. 
System.Threading.ThreadPool.QueueUserWorkItem( 
new System.Threading.WaitCallback(SomeLongTask)); 
// Queue another task. 
System.Threading.ThreadPool.QueueUserWorkItem( 
new System.Threading.WaitCallback(AnotherLongTask));
}

private void SomeLongTask(Object state)
{ 
// Insert code to perform a long task.
}

private void AnotherLongTask(Object state)
{ 
// Insert code to perform a long task.
}

Delegates:

The easy and popular way (debatable but still acceptable) of implementing delegates is by using BeginInvoke /& EndInvoke methods, such as:

//initialise the delegate public delegate void MyDelegateName();

//Call the delegate this.BeginInvoke(new MyDelegateName(MyFunction), new object[] { });

private void MyFunction(){

  

//Your Function Goes here.... }

You can also implement delegates the way which is mentioned in this MSDN Gallery Contribution: Cross-Threading Operation and Delegates (Using Control.Invoke Method) 

Note: This is a live document and a draft version, which lacks complete documentation of the techniques/technologies mentioned above. Please edit or include anything (features, advantages, disadvantages, etc.) which are being missed out. 

Thread MyNewThread = new Thread (MyFunction);  // Kick off a new thread MyNewThread.Start();  // running MyFunction()

Thread MyNewThread = new Thread (MyFunction);  // Kick off a new thread
MyNewThread.Start();  // running MyFunction()