Task.Factory.StartNew 和 Task.Run 到底有什么区别?

目录

前言

实现代码

DenyChildAttach

结论


 

前言

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

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值