Task Parallelism In Multithreading

Introduction

Task parallelism is the process of running tasks in parallel. Task parallelism divides tasks and allocates those tasks to separate threads for processing. It is based on unstructured parallelism. It means the parallel work unit may start and finish in places scattered according to the the executing of the program.
 
In this article we will be discussing task parallelism in Multi-threading.

Why Task? Why not Thread?

Below are the reasons to use Tasks instead of Thread:
  1. The creation of a thread leads to huge costs. It also brings an overhead of context switching within the application. So, it might bring a bad performance issue into a single-core environment.

  2. If we directly start a thread then it will create a new thread. It will not execute on the thread pool.
Why Task? Why not Thread Pools?

Thread Pool is a wrapper around a pool of threads maintained by the CLR. It does not give any control. You can control the size of the pool but you can't sset anything else.

If you submit too many long-running works to complete to thread pool then it will be full and your work will end up with the finishing up of long-running waiting items. It does not provide any way to find out when a work item has been completed and there's no way to get the result.

It should be used for the short operations and work where the callTer does not need any result.

Task
does not create its own new O/S thread as thread pool creates. It allows us to find out when it finishes and to getthe result.

When to not use Thread Pool Thread?

Below are the several cases in which Thread Pool should not be used. It will be better to create and manage your own thread.
  1. Ifa  foreground thread is required.
  2. If there is a task that causes the thread to block for long periods of time.
Creating Tasks

TPL allows different ways to create tasks. But, te hbelow namespace should be added before creating any tasks:
  1. using System.Threading.Tasks;  
Below are the different ways to create a task:
  1. Most Direct way:
    1. Task.Factory.StartNew(() => {Console.WriteLine("Hello Task library!"); });  
  2. Using Action:
    1. Task task = new Task(new Action(PrintMessage));  
    2. task.Start();  
    3. private void PrintMessage()  
    4. {  
    5.     Console.WriteLine("Hello World!");  
    6. }  
  3. Using Delegate:
    1. task = new Task(delegate { PrintMessage(); });  
    2. task.Start();  
  4. Lambda and named method:
    1. Task task = new Task( () => MyMessage() );  
    2. task.Start();  
  5. Lambda and anonymous method:
    1. Task task = new Task( () => { PrintMessage(); } );  
    2. task.Start();  
Create Task implicitly

Below are the concepts to create Task implicitly:
  1. It is maintained by framework.
  2. It should be used when you need to execute some work which does not return any value and does not need more control over these.
Below is the syntax:

Parallel.Invoke(() => MyFirstWork(), () => MySecondWork());

It provides two methods:
  1. Parallel.Invoke()
  2. Parallel.Invoke(ParallelOptions, Action[])
Create Task explicitly

Below are the some concepts to create Task explicitly:
  1. It is created and maintained by the developer.
  2. It is being used when we need more control over the tasks or return result.
Below are the two constructors of Task to create Task:
  1. Task: The Task constructor can be used to create a task where no return value is required. But, it allows us to control other behaviors.

    E.g. Task(Action), Task(Action, CancellationToken), Task(Action, TaskCreationOptions), etc.

    Namespace:
    1. System.Threading.Tasks.Task  
    Example:
    1. public void MyTasksWithWait()  
    2. {  
    3.     Thread.CurrentThread.Name = "Main Thread";  
    4.     Task taskA = new Task(() => Console.WriteLine("Hello from Task A"));  
    5.     //Start TaskA  
    6.     taskA.Start();  
    7.     Console.WriteLine("Hello from thread {0}", Thread.CurrentThread.Name);  
    8.     taskA.Wait();  
    9. }  
    Output:

    Hello from thread Main Thread.
    Hellow from thread A.


  2. Task<TResult>: This constructor allowsus  to create a Task with return value. It also allows us to control other behaviors.

    E.g. Task<TResult>(Func<TResult>), etc.

    Namespace:
    1. System.Threading.Tasks.Task<TResult>  
    Example:
    1. public void TaskReturningResult()  
    2. {  
    3.     var t = Task < int > .Run(() =>  
    4.     {  
    5.         // Just loop.  
    6.         int max = 1000000;  
    7.         int value = 0;  
    8.         for (value = 0; value <= max; value++)  
    9.         {  
    10.             if (value == max / 2 && DateTime.Now.Hour <= 12)  
    11.             {  
    12.                 value++;  
    13.                 break;  
    14.             }  
    15.         }  
    16.         return value;  
    17.     });  
    18.     Console.WriteLine("Finished {0:N0}.", t.Result);  
    19. }  
    Output:

    It will display output as below:

    Finished 1,000,001
Conclusion

So, Task Parallelism is a concept of threading wrapper. I will explain its remaining parts in the next article.

Reference


Similar Articles