C# 中Task的核心讲解(线程的高级用法)

来源: C# 中Task的核心讲解(线程的高级用法)

Task 概述

Task 是 .NET 中用于表示异步操作的类,属于 System.Threading.Tasks 命名空间。它封装了一个异步操作,提供状态管理、取消支持、延续任务等功能,是编写异步代码的核心组件之一。

Task 的核心特性

  • 异步执行

    :Task 可以在后台线程或线程池中运行,避免阻塞主线程。

  • 状态跟踪

    :提供 Status 属性(如 RanToCompletionFaultedCanceled)。

  • 结果获取

    :通过 Result 属性获取返回值(泛型 Task<T>)。

  • 取消支持

    :结合 CancellationToken 实现任务取消。

  • 延续任务

    :通过 ContinueWith 定义任务完成后的操作。


常用使用方法

创建并启动 Task

使用 Task.Run 或 Task.Factory.StartNew 启动一个后台任务:


// 1. 使用 Task.Run(最常用)
staticvoidMain(string[] args)
 {
// 1. 使用构造函数(需要手动启动)
     Task task1 = new Task(() =>
     {
         Thread.Sleep(100);
         Console.WriteLine($"hello,task1的线程ID为{Thread.CurrentThread.ManagedThreadId}");
     });
     task1.Start();

// 2. 使用 Task.Factory.StartNew
     Task task2 = Task.Factory.StartNew(() =>
     {
         Thread.Sleep(100);
         Console.WriteLine($"hello,task2的线程ID为{Thread.CurrentThread.ManagedThreadId}");
     });
//3.使用 Task.Run(最常用)
     Task task3 = Task.Run(() => 
     {
         Thread.Sleep(100);
         Console.WriteLine($"hello,task3的线程ID为{Thread.CurrentThread.ManagedThreadId}");

     });
     Console.WriteLine($"主线程ID为{Thread.CurrentThread.ManagedThreadId}");
     Console.ReadKey();
 }

执行结果如下,可以看到先输出了 “主线程ID为1”,说明了Task不会阻塞主线程,并且线程执行是无序的

我们也可以创建有返回值的Task,用法和没有返回值的基本一致,,代码如下:


Task task1 = new Task(() =>
{
    Thread.Sleep(100);
return ($"task1的线程ID为{Thread.CurrentThread.ManagedThreadId}");

});
task1.Start();

Task task2 = Task.Factory.StartNew(() =>
{
    Thread.Sleep(100);
return222;
});

Task task3 = Task.Run(() =>
{
    Thread.Sleep(100);
returntrue;
});

Console.WriteLine($"主线程ID为{Thread.CurrentThread.ManagedThreadId}");
Console.WriteLine(task1.Result);
Console.WriteLine(task2.Result);
Console.WriteLine(task3.Result);
Console.ReadKey();

执行结果如下:

task.Resut获取结果时会阻塞主线程,即如果task没有执行完成,会等待task执行完成获取到Result,所以这里是顺序执行。

等待 Task 完成

通过 WaitWaitAll 或 await 等待任务完成:

var task = Task.Run(()=>{
    Thread.Sleep(1000);
    return"完成";
});

// 阻塞等待
task.Wait();
Console.WriteLine(task.Result);

// 异步等待(需在 async 方法中使用)
string result = await task;

处理 Task 返回值

使用泛型 Task<T> 获取返回值:

Task<int> task = Task.Run(()=>{
  return 42;
});
Console.WriteLine(task.Result);// 输出 42

任务延续(ContinueWith)

在任务完成后执行后续操作:

Task.Run(()=>{
    Console.WriteLine("任务1");
}).ContinueWith(prevTask =>{
    Console.WriteLine("任务2");
});

取消 Task

通过 CancellationToken 实现任务取消:

var cts = new CancellationTokenSource();
var task = Task.Run(()=>{
while(true){
    cts.Token.ThrowIfCancellationRequested();
    Thread.Sleep(100);
}
}, cts.Token);

cts.CancelAfter(1000);// 1秒后取消

异常处理

通过 AggregateException 捕获任务异常:

try{
    Task.Run(()=>throw new Exception("错误")).Wait();
}catch(AggregateException ex){
    Console.WriteLine(ex.InnerException.Message);
}

最佳实践


  • 避免 Task.Result 或 Task.Wait 导致死锁(尤其在 UI 线程中)。


  • 使用 Task.WhenAll 并行执行多个任务:

Task<int> task1 = Task.Run(()=>1);
Task<int> task2 = Task.Run(()=>2);
int[] results = await Task.WhenAll(task1, task2);

Task 是现代 C# 异步编程的基础,合理使用可提升程序性能和响应能力。

赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏