欢迎光临
我们一直在努力

C# Task 异步任务

一、Task 异步任务三种创建方式

1. 核心原理

Task 是 .NET 新一代异步任务封装,替代传统 Thread,更轻量、可管控、支持取消、支持返回值、自带任务状态。

主流三种创建方式:

  • new Task():手动创建,需要手动 Start() 启动

  • Task.Run():静态方法,创建并自动启动(最常用)

  • Task.Factory.StartNew():任务工厂创建,功能更全面

2. 独立代码演示

// 方式1:new Task 手动创建 + 手动Start
Task t1 = new Task(DoWork);
t1.Start();

// 支持Lambda简写
Task t2 = new Task(() =>
{
Console.WriteLine("自定义任务");
});

// 方式2:Task.Run 静态创建(自动运行,开发最常用)
Task.Run(() =>
{
Console.WriteLine("Task.Run 自动执行");
});

// 方式3:任务工厂创建
Task.Factory.StartNew(() =>
{
Console.WriteLine("Factory 创建任务");
});

3. 注意事项

  • new Task 创建的任务必须手动 Start(),否则不执行

  • Task.Run 创建后自动启动,无需 Start

  • Task 相比 Thread 支持状态判断、取消、返回值、回调,功能更强


二、Task 带参数、带取消令牌 CancellationTokenSource

1. 核心原理

CancellationTokenSource(取消令牌):专门用于安全终止 Task 异步任务,替代粗暴的线程 Abort 终止。

核心机制:

  • cts.Token:通行证,绑定给 Task

  • cts.Cancel():触发取消请求

  • cts.IsCancellationRequested:判断是否收到取消信号

2. 完整可运行代码

Task t1 = null;
// 创建取消令牌对象
CancellationTokenSource cts = new CancellationTokenSource();
int i = 0;

private void button1_Click(object sender, EventArgs e)
{
// 如果任务完成,必须重置令牌(一个任务对应一个令牌)
if (t1 != null && t1.IsCompleted)
{
cts = new CancellationTokenSource();
t1 = new Task(DoWork, cts.Token);
}
t1.Start();
}

// 取消任务
private void button2_Click(object sender, EventArgs e)
{
cts.Cancel(); // 发送取消信号
}

// 异步任务逻辑
public void DoWork()
{
// 根据取消信号判断是否继续执行
while (!cts.IsCancellationRequested)
{
Invoke(new Action(() =>
{
label1.Text = i.ToString();
}));
i++;
}
}

3. Task 三大状态属性

t1.IsCompleted; // 是否正常执行完成
t1.IsCanceled; // 是否因为取消而结束
t1.IsFaulted; // 是否因为异常崩溃结束

4. 注意事项

  • 每个新 Task 必须 new 新的 CancellationTokenSource,旧令牌不可复用

  • 禁止使用 Abort 终止 Task,必须使用取消令牌,安全无异常

  • IsCancellationRequested 默认 false,调用 Cancel() 后变为 true

  • 任务重启前必须判断 IsCompleted,防止重复启动报错


三、泛型 Task 带返回值(Task<T>)

1. 核心原理

普通 Task 无返回值,泛型 Task<T> 可以让异步任务执行完毕后返回指定类型结果,通过 .Result 获取返回值。

2. 多层返回值代码演示(全覆盖)

// 1. 返回int
Task<int> t1 = new Task<int>(() => { return 100; });

// 2. 返回string
Task<string> t2 = new Task<string>(() => { return "哈兰德"; });

// 3. 返回Task(任务嵌套)
Task<Task> t3 = new Task<Task>(() =>
{
return new Task(() => { });
});

// 4. 返回带返回值的Task
Task<Task<int>> t4 = new Task<Task<int>>(() =>
{
return new Task<int>(() => 100);
});

// 5. 多层嵌套任务
Task<Task<Task>> t5 = new Task<Task<Task>>(() =>
{
return new Task<Task>(() =>
{
return new Task(() => { });
});
});

3. 注意事项

  • Task<T> 必须 return 对应类型数据

  • 嵌套 Task 多用于复杂异步编排,日常开发极少使用

  • 普通 Task 等同于 Task<void>(无返回值)


四、异步任务结果获取(阻塞获取 + 回调获取)

1. 核心原理

获取 Task 返回值有两种方式:

  • .Result:主线程阻塞等待任务结束,卡死UI,禁止在窗体使用

  • ContinueWith:任务执行完毕后自动回调,不阻塞UI,推荐

2. 对比代码演示

private void button1_Click(object sender, EventArgs e)
{
// 创建带返回值任务
Task<string> t1 = new Task<string>(() =>
{
Thread.Sleep(2000);
return "魔笛-莫迪老仙";
});
t1.Start();

// 【方式1:错误写法】Result 阻塞主线程,窗体卡死
// string res = t1.Result;

// 【方式2:正确写法】ContinueWith 回调获取结果,不阻塞UI
t1.ContinueWith(t =>
{
// 子线程回调获取结果
Console.WriteLine("任务结果:" + t.Result);
});
}

3. 注意事项

  • WinForm 中绝对禁止直接调用 .Result,会直接卡死界面

  • ContinueWith 是任务完成后的异步回调,不会阻塞主线程

  • 回调内部属于子线程,如需更新UI必须 Invoke


五、整体知识点总结

  • Task三种创建:new Task手动启动、Task.Run自动启动、Factory工厂创建

  • 取消令牌:cts 安全终止任务,替代Abort,新任务必须新令牌

  • 任务状态:IsCompleted、IsCanceled、IsFaulted 判断任务执行情况

  • 泛型Task:Task<T> 实现异步任务返回值

  • 结果获取:Result阻塞卡死、ContinueWith异步回调安全获取

赞(0)
未经允许不得转载:171主机测评 » C# Task 异步任务
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址