C# 中的任务并行库 (TPL)

作者:微信公众号:【架构师老卢】
3-12 18:17
23

概述:TPL 在 C# 中代表“任务并行库”。它是 .NET Framework 提供的一组类和 API,用于简化编写_并行和异步代码的过程。TPL 使开发人员能够更轻松地利用多核处理器并编写可同时执行任务的代码,从而提高其应用程序的性能。TPL 中的概念是“Task”类,它表示可以与其他任务同时运行的异步操作。开发人员可以使用任务来并行化操作、管理异步操作以及编写复杂的异步工作流。TPL 提供了用于管理任务的各种功能和构造,例如并行循环、用于异步编程的“async”和“await”关键字,以及用于协调多个任务的方法,例如“Task.WhenAll”和“Task.WhenAny”。_异步编程与并行编

TPL 在 C# 中代表“任务并行库”。它是 .NET Framework 提供的一组类和 API,用于简化编写_并行和异步代码的过程。TPL 使开发人员能够更轻松地利用多核处理器并编写可同时执行任务的代码,从而提高其应用程序的性能。TPL 中的概念是“Task”类,它表示可以与其他任务同时运行的异步操作。开发人员可以使用任务来并行化操作、管理异步操作以及编写复杂的异步工作流。TPL 提供了用于管理任务的各种功能和构造,例如并行循环、用于异步编程的“async”“await”关键字,以及用于协调多个任务的方法,例如“Task.WhenAll”“Task.WhenAny”。_

异步编程与并行编程

异步编程

  1. 允许_单个线程有效地处理多个任务而不会阻塞:主要关注点是响应能力。并且还可以释放线程来执行其他工作,同时等待缓慢不可预测的_操作完成
  2. 使用 和 关键字实现。asyncawait
  3. 例如:读取文件、发出网络请求或等待用户输入。

并行编程

  1. 将任务划分为更小的子任务,并使用_多个线程或进程同时_执行这些子任务,以提高性能。
  2. 可以使用任务并行库 (TPL) 实现。
  3. 例如:CPU 密集型任务,可利用多个 CPU 内核更快地执行计算

分步指南

  1. 命名空间
using System;  
using System.Threading.Tasks;

2. 使用返回值创建任务

//create a new task called task1  
Task task1 = Task.Run(() => {  
    return true;  
});  
  
//use value of task1  
bool result = task1.Result;

3.等待任务完成

// This blocks wait until task1 is completed  
task1.Wait();   
  
// This blocks wait until all tasks of the taskArray are completed  
Task.WaitAll(taskArray);  
  
// This blocks wait until any task of the taskArray is completed  
Task.WaitAny(taskArray);

4. 任务延续

ContinueWith用于指定在_上一个任务完成后应运行的延续任务。它允许您创建一系列任务,其中一个任务的完成会触发另一个任务的执行。默认情况下,不等待上一个任务完成。相反,它会在上一个任务完成后立即开始运行_,而不管上一个任务是成功还是遇到异常。这种行为通常被称为“**即发即弃”。**ContinueWith"

//create a task called task1 and return integer value   
Task<int> task1 = Task.Run(() => 42);  
  
//create task2 with a continuation on task1  
Task<string> task2 = task1.ContinueWith(previousTask => {  
    //get the task1 returning data  
    int result = previousTask.Result;  
    return $"previous task return value is {result}";  
});

解释:

当您在 continue on 的情况下创建时,继续任务 () 将等到完成后才开始执行。因此,在完成执行之前不会开始。task4task3task4task3task4task3

  • task3 是使用 Task.Run(() => 42) 创建并启动的。
  • task4 是使用 ContinueWith 方法创建的,作为 task3 的延续。
  • 由于 task3 在创建 task4 之前就已启动,因此 task4 将等待 task3 完成,然后再开始执行。
  • 一旦 task3 完成(在本例中,当它返回值 42 时),task4 将执行其代码。

5. TaskFactory.Start新建

在一个操作中创建并启动任务。

Task.Factory.StartNew(() => DoComputation(1.0));  
  
private static Double DoComputation(Double start)  
{  
      Double sum = 0;  
      for (var value = start; value <= start + 10; value += .1)  
         sum += value;  
  
      return sum;  
 }

6. 分离的子任务

父任务和子任务之间没有同步。父任务不会等待分离的子任务完成。

var outer = Task.Factory.StartNew(() =>  
{  
    Console.WriteLine("Outer task beginning.");  
  
    var child = Task.Factory.StartNew(() =>  
    {  
        Thread.SpinWait(5000000);  
        Console.WriteLine("Detached task completed.");  
    });  
});  
  
outer.Wait();  
Console.WriteLine("Outer task completed.");  
  
// The example displays the following output:  
//    Outer task beginning.  
//    Outer task completed.  
//    Detached task completed.

7. 附加的子任务

通过指定选项。AttachToParent

public static void Main()  
{  
      var parent = Task.Factory.StartNew(() => {  
                      Console.WriteLine("Parent task beginning.");  
                      for (int ctr = 0; ctr < 10; ctr++) {  
                         int taskNo = ctr;  
                         Task.Factory.StartNew((x) => {  
                                                  Thread.SpinWait(5000000);  
                                                  Console.WriteLine("Attached child #{0} completed.",  
                                                                    x);  
                                               },  
                                               taskNo, TaskCreationOptions.AttachedToParent);  
                      }  
                   });  
  
      parent.Wait();  
      Console.WriteLine("Parent task completed.");  
}  
  
// The example displays output like the following:  
//       Parent task beginning.  
//       Attached child #9 completed.  
//       Attached child #0 completed.  
//       Attached child #8 completed.  
//       Attached child #1 completed.  
//       Attached child #7 completed.  
//       Attached child #2 completed.  
//       Attached child #6 completed.  
//       Attached child #3 completed.  
//       Attached child #5 completed.  
//       Attached child #4 completed.  
//       Parent task completed.

8. 任务示例

使用方法时会传播异常,并通过添加语句来处理异常。异常类型为 。Task.Wait()Task.Wait()try & catchAggregateException

public static partial class Program  
{  
    public static void HandleThree()  
    {  
        var task = Task.Run(  
            () => throw new CustomException("This exception is expected!"));  
  
        try  
        {  
            task.Wait();  
        }  
        catch (AggregateException ae)  
        {  
            foreach (var ex in ae.InnerExceptions)  
            {  
                // Handle the custom exception.  
                if (ex is CustomException)  
                {  
                    Console.WriteLine(ex.Message);  
                }  
                // Rethrow any other exception.  
                else  
                {  
                    throw ex;  
                }  
            }  
        }  
    }  
}  
  
// The example displays the following output:  
//        This exception is expected!

9. 附加的子任务示例

通过访问内部异常。

public static partial class Program  
{  
    public static void FlattenTwo()  
    {  
        var task = Task.Factory.StartNew(() =>  
        {  
            var child = Task.Factory.StartNew(() =>  
            {  
                var grandChild = Task.Factory.StartNew(() =>  
                {  
                    // This exception is nested inside three AggregateExceptions.  
                    throw new CustomException("Attached child2 faulted.");  
                }, TaskCreationOptions.AttachedToParent);  
  
                // This exception is nested inside two AggregateExceptions.  
                throw new CustomException("Attached child1 faulted.");  
            }, TaskCreationOptions.AttachedToParent);  
        });  
  
        try  
        {  
            task.Wait();  
        }  
        catch (AggregateException ae)  
        {  
            foreach (var ex in ae.Flatten().InnerExceptions)  
            {  
                if (ex is CustomException)  
                {  
                    Console.WriteLine(ex.Message);  
                }  
                else  
                {  
                    throw;  
                }  
            }  
        }  
    }  
}  
// The example displays the following output:  
//    Attached child1 faulted.  
//    Attached child2 faulted.

10. 异步状态

public static void Main()  
{  
        //Create array of tasks  
        Task[] taskArray = new Task[10];  
          
        //Assign, create and run tasks into task array  
        for (int i = 0; i < taskArray.Length; i++)  
        {  
            taskArray[i] = Task.Factory.StartNew((Object obj) =>  
            {  
                CustomData data = obj as CustomData;  
                if (data == null) return;  
  
                data.ThreadNum = Thread.CurrentThread.ManagedThreadId;  
            },  
            new CustomData() { Name = i, CreationTime = DateTime.Now.Ticks });  
        }  
  
        //This waits until all tasks of the taskArray are completed  
        Task.WaitAll(taskArray);  
  
          
        foreach (var task in taskArray)  
        {  
            var data = task.AsyncState as CustomData;  
            if (data != null)  
                Console.WriteLine("Task #{0} created at {1}, ran on thread #{2}.",  
                                  data.Name, data.CreationTime, data.ThreadNum);  
        }  
}  
  
// The example displays output like the following:  
//     Task #0 created at 635116412924597583, ran on thread #3.  
//     Task #1 created at 635116412924607584, ran on thread #4.  
//     Task #2 created at 635116412924607584, ran on thread #4.  
//     Task #3 created at 635116412924607584, ran on thread #4.  
//     Task #4 created at 635116412924607584, ran on thread #3.  
//     Task #5 created at 635116412924607584, ran on thread #3.  
//     Task #6 created at 635116412924607584, ran on thread #4.  
//     Task #7 created at 635116412924607584, ran on thread #4.  
//     Task #8 created at 635116412924607584, ran on thread #3.  
//     Task #9 created at 635116412924607584, ran on thread #4.

通过使用相关类型并强制转换它,您可以从任务中获取数据。

相关留言评论
昵称:
邮箱:
阅读排行