C# Task异步的常用方法

Task异步的常用方法

C# 中的 Task 类是 System.Threading.Tasks 命名空间的一部分,用于表示异步操作。

一、Task.Run(Action action):

此静态方法用于在后台运行一个新任务,并返回与该任务关联的 Task 实例。

  1. 本质是将任务放入线程池执行,自动启动,适合CPU 密集型或简单异步操作。
  2. 注意:返回的 Task 无法手动控制启动(已自动启动)。
cs 复制代码
Task.Run(() => Console.WriteLine("后台执行"));

二、Task.Start():

用于手动启动通过 new Task(...) 创建的未启动任务 (默认状态为 Created)。

cs 复制代码
var task = new Task(() => Console.WriteLine("手动启动"));
task.Start(); // 必须调用才会执行

三、Task.Delay(int millisecondsDelay):

此静态方法创建一个在指定延迟之后完成的 Task。这对于定时操作或模拟长时间运行的任务非常有用。

cs 复制代码
await Task.Delay(1000); // 等待1秒

四、任务等待相关方法(阻塞 vs 非阻塞)

方法 特性 适用场景
await Task.WhenAll 非阻塞等待所有任务完成 异步方法中,需要等待多个任务全部完成后再继续
await Task.WhenAny 非阻塞等待任一任务完成 异步方法中,只需等待最快完成的任务结果
Task.WaitAll 阻塞当前线程等待所有任务 同步方法中强制等待(不推荐在异步代码中使用)
Task.WaitAny 阻塞当前线程等待任一任务 同步方法中需立即响应第一个完成的任务
Task.Wait() 阻塞当前线程等待单个任务 同步方法中等待单个任务(等价于 WaitAll 单任务)

关键区别:

  1. await 搭配 WhenAll/WhenAny 是非阻塞等待,会释放当前线程,适合异步上下文(如 UI 线程),避免界面卡顿。
  2. Wait()/WaitAll()/WaitAny() 是阻塞等待 ,会冻结当前线程,可能导致性能问题(如 UI 无响应),仅建议在纯同步代码中使用。

1.Task.WhenAll(Task\[\] tasks):

注意:由于此调用不会默认等待,需要再前面添加await。

cs 复制代码
var task1 = Task.Run(() => { /* 任务1 */ });
var task2 = Task.Run(() => { /* 任务2 */ });
 
await Task.WhenAll(task1, task2);

2.Task.WhenAny(Task\[\] tasks):

注意:由于此调用不会默认等待,需要再前面添加await。

cs 复制代码
var task1 = Task.Run(() => { /* 任务1 */ });
var task2 = Task.Run(() => { /* 任务2 */ });
 
var completedTask = await Task.WhenAny(task1, task2);

3.Task.Wait():

cs 复制代码
var task = Task.Run(() => { /* 代码 */ });
task.Wait();

4.Task.WaitAll(Params Task\[\])

cs 复制代码
var task1 = Task.Run(() => { /* 任务1 */ });
var task2 = Task.Run(() => { /* 任务2 */ });
 
var completedTask = Task.WaitAll(task1, task2);

5.Task.WaitAny(Params Task\[\])

cs 复制代码
var task1 = Task.Run(() => { /* 任务1 */ });
var task2 = Task.Run(() => { /* 任务2 */ });
 
var completedTask = Task.WaitAny(task1, task2);

五、Task.ContinueWith(Action continuationAction):

此方法用于在当前任务完成后执行另一个操作。这对于链式(嵌套)任务执行非常有用。(等待一个任务完成)

cs 复制代码
// 正常情况下 t1 和 t2 不知道谁先执行完
Task<string> t1 = new Task<string>(F1);
Task<string> t2 = new Task<string>(F2);
Task<string> t3 = new Task<string>(F3);
 
//t1先执行 t2后执行 
t1.ContinueWith(t =>
{
    // t1执行完之后 再去执行
    t2.Start(); //第二任务
    t2.ContinueWith(t4 =>
    {
        //第二个任务完成了
        //第三个任务对象
        t3.Start();
        t3.ContinueWith(t5 =>
        {
            Console.WriteLine("保证第三个任务完成");
        });
    });
});

注意:在使用 Task 类时,应始终考虑处理异常和取消操作。这可以通过使用 try-catch 语句和 CancellationToken 来实现。

相关推荐
胖纸不争11 小时前
嫌桌面 Agent 太重,我“自己”写了一个
ai·c#·net core
当青春邂逅吉米多维奇15 小时前
C#图解教程(第5版) 同步方法
开发语言·c#
波力海苔夹心脆67515 小时前
C# 机器视觉实战:单相机引导机械手精准贴合,从拍照、偏差计算(平移+旋转)到坐标补偿全解
开发语言·经验分享·数码相机·c#·视觉检测·.net
Behavior17 小时前
国内下载使用 Unity 6000 踩坑点总结
c#·unity3d·游戏开发
czhc114007566318 小时前
一张图从哪来,一个判断往哪走
c#
曹牧1 天前
C#:未被引用的函数
c#
上位机妹子1 天前
EF Core 两种继承映射:每层次一张表(TPH)与每类型一张表(TPT)
数据库·c#·.netcore·ef core
小羊没烦恼!2 天前
jQuery1.5的改进细节
java·服务器·开发语言·前端·c#
下页、再停留2 天前
【C#桌面客户端系列学习-8】批量导出数据为csv格式
开发语言·c#·visual studio
波力海苔夹心脆6752 天前
C# 视觉检测实战:PLC 按钮触发 VisionPro 检测,OK 亮灯 / NG 灭灯(西门子 PLC,含界面显示与图片存档)
开发语言·经验分享·c#·自动化·视觉检测·.net