一、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异步回调安全获取






