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 来实现。

相关推荐
唐青枫33 分钟前
C#.NET log4net 详解
c#·.net
Nemo_XP6 小时前
HttpHelper类处理两种HTTP POST请求
c#
lijingguang13 小时前
在C#中根据URL下载文件并保存到本地,可以使用以下方法(推荐使用现代异步方式)
开发语言·c#
¥-oriented13 小时前
【C#中路径相关的概念】
开发语言·c#
ArabySide14 小时前
【WCF】通过AOP实现基于JWT的授权与鉴权的实践
c#·jwt·aop·wcf
阿蒙Amon14 小时前
C# Linq to Objects 详解:集合处理的终极方案
c#·solr·linq
钢铁男儿14 小时前
C# 委托(调用带引用参数的委托)
java·mysql·c#
番茄小能手15 小时前
【全网唯一】C# 纯本地离线文字识别Windows版dll插件
开发语言·c#
葬歌倾城16 小时前
waferMap图像渲染
c#·wpf