The Task Parallel Library (TPL) is based on the concept called task. The task parallelism means, running one or more independent tasks concurrently. A task represents an asynchronous operation, and in some ways it resembles the creation of a new thread or ThreadPool work item, but at a higher level of abstraction.
Also check out:
- ExecuteNonQuery(), ExecuteReader() and ExecuteScalar() in Ado.Net
- How to validate user input for mobile number using Regular Expression in Javascript?
- Get all tables and stored procedures in sql server 2008
Tasks provide two primary benefits:
- More efficient and more scalable use of system resources.
Behind the scenes, tasks are queued to the ThreadPool, which has been enhanced with algorithms (like hill-climbing) that determine and adjust to the number of threads that maximizes throughput. So that tasks are relatively lightweight.
- More programmatic control than which is possible with a thread or work item.
Tasks and the framework built around the task provides a rich set of APIs that support waiting, cancellation, continuations, robust exception handling, detailed status, custom scheduling, and more.
Creating and Running Tasks Implicitly:
The Parallel.Invoke method provides a convenient way to run any number of arbitrary statements concurrently. Just pass in an Action delegate for each item of work. The easiest way to create these delegates is to use lambda expressions. The lambda expression can either call a named method, or provide the code inline.
// basic Invoke call that creates and starts two tasks mytask1,
// mytask2 that run concurrently.
Parallel.Invoke(() => mytask1(), () => mytask2());
Creating and running Tasks Explicitly:
A task is represented by the System.Threading.Tasks.Task class. A task that returns a value is represented by the System.Threading.Tasks.Task<TResult> class, which inherits from Task class. The task object handles the infrastructure details, and provides methods and properties that are accessible from the calling thread throughout the lifetime of the task. For example, you can access the Status property of a task at any time to determine whether it has started running, ran to completion, was canceled, or has thrown an exception. The status is represented by a TaskStatus enumeration. When you create a task, you give it a user delegate that encapsulates the code that the task will execute. The delegate can be expressed as a named delegate, an anonymous method, or a lambda expression.
// Create a task and supply a user delegate by using a lambda expression.
var taskA = new Task(() => Console.WriteLine("this is from taskA."));
// Start the task.
taskA.Start();
// Output a message from the joining thread.
Console.WriteLine("this is from calling thread.");
You can also use the Run or StartNew methods to create and start a task in one operation.
Creating detached nested task:
When user code that is running in a task creates a new task without the AttachedToParent option, then it is not synchronized with the outer task in any way. Such tasks are called a detached nested task. The outer task does not wait for the nested task to finish.
// task that creates one detached nested task
var outer_task = Task.Factory.StartNew(() =>
{
Console.WriteLine("Outer task beginning.");
var child = Task.Factory.StartNew(() =>
{
Thread.SpinWait(400000);
Console.WriteLine("Detached task completed.");
});
});
Creating child task:
When user code that is running in a task creates a task with the AttachedToParent option, the new task is known as a child task of the originating task, which is known as the parent task. The AttachedToParent option can be used to express structured task parallelism, because the parent task implicitly waits for all child tasks to finish.
// task that creates a child task
var parent = Task.Factory.StartNew(() =>
{
Console.WriteLine("Parent task begins....");
var child = Task.Factory.StartNew(() =>
{
Thread.SpinWait(400000);
Console.WriteLine("Attached child completed...");
}, TaskCreationOptions.AttachedToParent);
});
parent.Wait();
Console.WriteLine("Parent task completed....");
Also check out:
- ExecuteNonQuery(), ExecuteReader() and ExecuteScalar() in Ado.Net
- How to validate user input for mobile number using Regular Expression in Javascript?
- Get all tables and stored procedures in sql server 2008
Tasks provide two primary benefits:
- More efficient and more scalable use of system resources.
Behind the scenes, tasks are queued to the ThreadPool, which has been enhanced with algorithms (like hill-climbing) that determine and adjust to the number of threads that maximizes throughput. So that tasks are relatively lightweight.
- More programmatic control than which is possible with a thread or work item.
Tasks and the framework built around the task provides a rich set of APIs that support waiting, cancellation, continuations, robust exception handling, detailed status, custom scheduling, and more.
Creating and Running Tasks Implicitly:
The Parallel.Invoke method provides a convenient way to run any number of arbitrary statements concurrently. Just pass in an Action delegate for each item of work. The easiest way to create these delegates is to use lambda expressions. The lambda expression can either call a named method, or provide the code inline.
// basic Invoke call that creates and starts two tasks mytask1,
// mytask2 that run concurrently.
Parallel.Invoke(() => mytask1(), () => mytask2());
Creating and running Tasks Explicitly:
A task is represented by the System.Threading.Tasks.Task class. A task that returns a value is represented by the System.Threading.Tasks.Task<TResult> class, which inherits from Task class. The task object handles the infrastructure details, and provides methods and properties that are accessible from the calling thread throughout the lifetime of the task. For example, you can access the Status property of a task at any time to determine whether it has started running, ran to completion, was canceled, or has thrown an exception. The status is represented by a TaskStatus enumeration. When you create a task, you give it a user delegate that encapsulates the code that the task will execute. The delegate can be expressed as a named delegate, an anonymous method, or a lambda expression.
// Create a task and supply a user delegate by using a lambda expression.
var taskA = new Task(() => Console.WriteLine("this is from taskA."));
// Start the task.
taskA.Start();
// Output a message from the joining thread.
Console.WriteLine("this is from calling thread.");
You can also use the Run or StartNew methods to create and start a task in one operation.
Creating detached nested task:
When user code that is running in a task creates a new task without the AttachedToParent option, then it is not synchronized with the outer task in any way. Such tasks are called a detached nested task. The outer task does not wait for the nested task to finish.
// task that creates one detached nested task
var outer_task = Task.Factory.StartNew(() =>
{
Console.WriteLine("Outer task beginning.");
var child = Task.Factory.StartNew(() =>
{
Thread.SpinWait(400000);
Console.WriteLine("Detached task completed.");
});
});
Creating child task:
When user code that is running in a task creates a task with the AttachedToParent option, the new task is known as a child task of the originating task, which is known as the parent task. The AttachedToParent option can be used to express structured task parallelism, because the parent task implicitly waits for all child tasks to finish.
// task that creates a child task
var parent = Task.Factory.StartNew(() =>
{
Console.WriteLine("Parent task begins....");
var child = Task.Factory.StartNew(() =>
{
Thread.SpinWait(400000);
Console.WriteLine("Attached child completed...");
}, TaskCreationOptions.AttachedToParent);
});
parent.Wait();
Console.WriteLine("Parent task completed....");