Hi, I’m Hui.

Having studied thread pools earlier, I know that they have many benefits.

Using thread pools allows us to save operating system resources while reducing parallelism costs. Think of the thread pool as a layer of abstraction that hides the details of using threads from the programmer, allowing us to focus on program logic rather than various threading issues.

This is not to say that all of our projects have thread pools, but it has many drawbacks, such as the need to customize the use of asynchronous delegates in order to pass messages or exceptions from threads. In a large software system, these can lead to overly chaotic software structures, messages passing from thread to thread, and fatal errors if unhandled exceptions occur.

To solve this problem, in. Net Framework 4.0 introduced a new API for asynchronous operations called task Parallel Library (TPL).

So let’s take a look at the TPL and see what magic it has to solve the thorny problem of thread pooling.

Task parallel library

TPL is also considered an abstraction of thread pools, hiding the underlying code of thread pool interactions from programmers and providing only a more convenient fine-grained API.

The core of TPL is the task. A task represents an asynchronous operation that can be run in a variety of ways, with or without a separate thread.

A key advantage of TPL is that a task can be combined with other tasks in a variety of ways.

For example, you can start multiple tasks at the same time, wait for all tasks to complete, and then run a task to do some calculations on the results of all previous tasks.

AggregateException can be used to capture all exceptions within the underlying task and allow these exceptions to be handled separately. TPL support has been built into C#5.0, allowing us to manipulate tasks in a smooth and comfortable manner using the proto-await and async keywords.

Create a task

There are three ways to create a task.

Var a1 = new Task(()=>TastMethod(" thread 01")); a1.Start(); Task. The Run (() = > TastMethod (" thread 001 ")); Task.factory.startnew (()=>TastMethod(" thread 02")); task.factory.startNew (()=>TastMethod(" thread 02")); Task. Factory. StartNew (() = > TastMethod (03 "threads"), TaskCreationOptions. LongRunning); Console.ReadKey();Copy the code

The quick task launch mode Run has been dropped in the latest.net 5.0 release. Only the other two can be used. Instantiated Tast property that must be started before the task can be executed. The rest of.NET has been built in and is automatically enabled by default if you only need to use it.

In the process of thread 3 open, increased TaskCreationOptions. LongRuning parameters, it said mark the task as long running, the results of the task will not be using the thread pool, and run in a separate thread. However, depending on the current task scheduler running the task, it may run differently.

2. Perform basic operations using tasks

Here are the results of the calculation returned from the task.

Static void Main(string[] args) {var a1 = new Task<int>(()=>TastMethod(" thread 01")); a1.Start(); int result = a1.Result; Console.WriteLine("result: "+ result); Console.ReadKey(); } static int TastMethod(string name) {Console.WriteLine(" threadname: +name+"Id: "+ Thread. CurrentThread. ManagedThreadId +" whether to belong to the Thread pool: "+ Thread. CurrentThread. IsThreadPoolThread); return 40; }Copy the code

Here we declare and run thread 01 and wait for the result, the task will be placed in the thread pool, and the main thread will wait and block until the task returns.

You can also call the method RunSynchronously() method to run in the main thread specifically. This is a nice optimization to avoid using thread pools for very short operations.

3. Handle exceptions in tasks

Exception handling is very important in asynchronous tasks.

Try {var a1 = new Task<int>(() => TastMethod(" thread 01",2)); a1.Start(); int result = a1.Result; Console.WriteLine("result: "+ result); } catch (Exception ex) { Console.WriteLine(ex.Message); }Copy the code

When the program starts, a task is created and an attempt is made to get the result of the task synchronously. The Get part of the Result attribute causes the current thread to wait until the task ends, propagating the exception to the current thread. This is easily caught by try/catch (note AggregateExceptiont, which is encapsulated).

int result = a1.GetAwaiter().GetResult ;
Copy the code

In this case, no encapsulation exception is required and the GetAwaiter and GetResult methods can be used to access the results of the task.

Small remarks

Life is short, I don’t want to go after what I can’t see, I just want to catch what I can see.

Original is not easy, give a attention.

I am Hui, thank you for reading, if it is helpful to you, please like, forwarding thank you.