Task.Factory.StartNew
和 Task.Run
都是用来启动新任务的,但它们有一些关键区别,我们来一条一条讲清楚(配例子 + 结论)。
🆚 1. 语法和使用目的
对比项 |
Task.Run |
Task.Factory.StartNew |
用途 |
简化写法,用于启动“后台任务” |
更底层、更灵活,用于高阶配置 |
返回值 |
Task |
Task , Task<TResult> ,可高度配置 |
引入版本 |
.NET 4.5 起 |
.NET 4.0 起 |
✅ 示例对比:
Task.Run
(推荐现代用法):
Task.Run(() => {
});
Task.Factory.StartNew
(配置能力强):
Task.Factory.StartNew(() => {
}, CancellationToken.None,
TaskCreationOptions.LongRunning,
TaskScheduler.Default);
🆚 2. 默认行为区别(重点⚠️)
项目 |
Task.Run |
Task.Factory.StartNew |
使用线程池 |
✅ 是 |
✅ 是 |
支持 async/await 正确传播上下文 |
✅ 是 |
⚠️ 否(默认不会) |
默认调度器 |
TaskScheduler.Default |
调用线程的调度器(可能不同) |
异步嵌套行为 |
✅ 自动 unwrap |
⚠️ 不自动 unwrap(会返回 Task<Task> ) |
❗ async lambda 注意区别:
await Task.Run(async () => {
await Task.Delay(1000);
});
Task.Factory.StartNew(async () => {
await Task.Delay(1000);
});
🆚 3. 适用场景
场景 |
推荐 |
启动后台任务,异步执行工作 |
✅ Task.Run |
需要高级配置(如 LongRunning、专用 TaskScheduler) |
✅ Task.Factory.StartNew |
和 async/await 配合 |
✅ Task.Run 更安全 |
想控制是否使用线程池、任务选项、调度器等 |
✅ StartNew 有更高自由度 |
✅ 总结推荐
- ✅ 日常写 async 或后台处理?用
Task.Run
,安全简洁。
- 🔧 有特殊需求(如长时间任务、不走线程池、UI 调度器)?用
Task.Factory.StartNew
。
🚨 最后提醒(常见坑):
Task.Factory.StartNew(async () => {
await Task.Delay(1000);
});
👇正确用法:
await Task.Run(async () => {
await Task.Delay(1000);
});