Task.Factory.StartNew 和 Task.Run 到底有什么区别?
Posted dotNET跨平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Task.Factory.StartNew 和 Task.Run 到底有什么区别?相关的知识,希望对你有一定的参考价值。
前言
Task.Factory.StartNew 和 Task.Run 都可以创建 Task:
Task.Factory.StartNew(() => Console.WriteLine("Task.Factory.StartNew"); );
Task.Run(() => Console.WriteLine("Task.Run"); );
那它们之间有什么区别呢?
实现代码
查看这 2 个方法的内部实现,其内部实现逻辑其实是一样的,只是传的默认参数不同:
//Task.Factory.StartNew
public Task StartNew(Action action)
Task? currTask = Task.InternalCurrent;
return Task.InternalStartNew(currTask, action, null, m_defaultCancellationToken, GetDefaultScheduler(currTask),
m_defaultCreationOptions, InternalTaskOptions.None);
//Task.Runpublic static Task Run(Action action)
return Task.InternalStartNew(null, action, null, default, TaskScheduler.Default,
TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None);
最关键的参数区别是 Task.Run 传入了 TaskCreationOptions.DenyChildAttach
。
那这个参数有什么用呢?
DenyChildAttach
查看官方文档[1]的解释,DenyChildAttach
的作用是阻止子任务附加到其父任务:
设想下从 Task 对象调用第三方库组件的应用。如果第三方库组件也创建一个 Task 对象,并指定 TaskCreationOptions.AttachedToParent 以将其附加到父任务中,则子任务中出现的任何未经处理的异常将会传播到父任务。这可能会导致主应用中出现意外行为。
创建代码验证一下:
Stopwatch stopwatch1 = new Stopwatch();
stopwatch1.Start();
var task1 = Task.Factory.StartNew(() =>
Run();
Console.WriteLine("Task.Factory.StartNew");
);
await task1;
stopwatch1.Stop();
Console.WriteLine(stopwatch1.ElapsedMilliseconds);
Stopwatch stopwatch2 = new Stopwatch();
stopwatch2.Start();
var task2 = Task.Run(() =>
Run();
Console.WriteLine("Task.Run");
);
await task2;
stopwatch2.Stop();
Console.WriteLine(stopwatch2.ElapsedMilliseconds);
Run
方法代表执行相同的第三方库组件调用,内部使用了 AttachedToParent
:
private static void Run()
Task.Factory.StartNew(() =>
Thread.Sleep(1000);
Console.WriteLine("Run");
, TaskCreationOptions.AttachedToParent);
运行程序,你将会看到类似的如下输出:
Task.Factory.StartNew
Run
1080
Task.Run
1
Run
使用 Task.Factory.StartNew
必须等待 AttachedToParent
任务执行完,而 Task.Run
不必。
结论
一般情况下,尽量使用 Task.Run
,如果需要更精细地控制任务的行为,比如 TaskCreationOptions
, 才使用 Task.Factory.StartNew
。
想了解更多内容,请关注我的个人公众号”My IO“
参考资料
[1]
官方文档: https://docs.microsoft.com/zh-cn/dotnet/standard/parallel-programming/attached-and-detached-child-tasks
以上是关于Task.Factory.StartNew 和 Task.Run 到底有什么区别?的主要内容,如果未能解决你的问题,请参考以下文章
Task.Factory.StartNew 和 Task.Run 到底有什么区别?
Task.Run() 和 Task.Factory.StartNew() 有啥区别
Task.Run 和 Task.Factory.StartNew 区别