前言

这不是和《Task.Factory.StartNew 和 Task.Run 到底有什么区别?》一样吗,怎么又写一篇?

起先我也是这么觉得的,但实际发现并非如此。

实现代码

查看这 2 个方法的内部实现,其内部实现逻辑其实是一样的,只是传的默认参数不同:

//Task.Factory.StartNew<TResult>
public Task<TResult> StartNew<TResult>(Func<TResult> function)
{Task? currTask = Task.InternalCurrent;return Task<TResult>.StartNew(currTask, function, m_defaultCancellationToken,m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
}//Task.Run<TResult>
public static Task<TResult> Run<TResult>(Func<TResult> function)
{return Task<TResult>.StartNew(null, function, default,TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None, TaskScheduler.Default);
}

这不还和上次一样吗?

Demo

让我们创建代码验证一下:

Stopwatch stopwatch1 = new Stopwatch();
stopwatch1.Start();
var task1 = Task.Factory.StartNew(async () =>
{await Task.Delay(1000);return "Task.Factory.StartNew";
});Console.WriteLine(await task1);
stopwatch1.Stop();
Console.WriteLine(stopwatch1.ElapsedMilliseconds);Stopwatch stopwatch2 = new Stopwatch();
stopwatch2.Start();
stopwatch2.Start();
var task2 = Task.Run(async () =>
{await Task.Delay(1000);return "Task.Run";
});Console.WriteLine(await task2);
stopwatch2.Stop();
Console.WriteLine(stopwatch2.ElapsedMilliseconds);

运行程序,你将会看到类似的如下输出:

System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[System.String,ConsoleApp1.Program+<>c+<<Main>b__0_0>d]
86
Task.Run
1024

是不是很你想的结果完全不一样!

使用 Task.Factory.StartNew<TResult> 的返回并不是 Task<string>,而是Task<Task<string>>:

这是为什么呢?

原理

其实是因为上述代码传入的参数类型不是 Func<TResult> 而是 Func<Task<TResult>?>,而 Task.Run<Task<TResult>?> 对此做了一层封装:

public static Task<TResult> Run<TResult>(Func<Task<TResult>?> function, CancellationToken cancellationToken)
{...Task<Task<TResult>?> task1 = Task<Task<TResult>?>.Factory.StartNew(function, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);UnwrapPromise<TResult> promise = new UnwrapPromise<TResult>(task1, lookForOce: true);return promise;
}

内部同样使用 Task.Factory.StartNew<Task<TResult>?> 生成任务,但是返回的是 UnwrapPromise<TResult>:

// This class encapsulates all "unwrap" logic, and also implements ITaskCompletionAction,
// which minimizes the allocations needed for queuing it to its antecedent.  This
// logic is used by both the Unwrap extension methods and the unwrap-style Task.Run methods.
internal sealed class UnwrapPromise<TResult> : Task<TResult>, ITaskCompletionAction

Task.Factory.StartNew<TResult> 没有这层封装。

不过,要想Task.Factory.StartNew<TResult>达到Task.Run<TResult>同样目的,可以使用 Unwrap 方法:

public static Task<TResult> Unwrap<TResult>(this Task<Task<TResult>> task!!) =>// If the task hasn't completed or was faulted/canceled, wrap it in an unwrap promise. Otherwise,// it completed successfully.  Return its inner task to avoid unnecessary wrapping, or if the inner// task is null, return a canceled task to match the same semantics as CreateUnwrapPromise.!task.IsCompletedSuccessfully ? Task.CreateUnwrapPromise<TResult>(task, lookForOce: false) :task.Result ??Task.FromCanceled<TResult>(new CancellationToken(true));//使用示例
var task1 = Task.Factory.StartNew(async () =>
{await Task.Delay(1000);return "Task.Factory.StartNew";
});Console.WriteLine(await task1.Unwrap());

结论

在使用 Task.Factory.StartNew 时,如果需要等待内部任务的最终完成,需要使用 Unwrap 方法进行“解开”。

想了解更多内容,请关注我的个人公众号”My IO“

Task.Factory.StartNewTResult 和 Task.RunTResult 到底有什么区别?相关推荐

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

    前言 Task.Factory.StartNew 和 Task.Run 都可以创建 Task: Task.Factory.StartNew(() => { Console.WriteLine(& ...

  2. Task.Factory.StartNew 和 Task.Factory.FromAsync 有什么区别?

    咨询区 soleiljy 假设我们有一个涉及IO操作的方法 (读取数据库),这个方法支持以同步或者异步的方式执行. 同步方式 IOMethod() 异步方式 BeginIOMethod()  EndI ...

  3. C# Task.Run 和 Task.Factory.StartNew 区别

    有小伙伴问我,为什么不推荐他使用 Task.Factory.StartNew ,因为 Task.Run 是比较新的方法. 本文告诉大家 Task.Run 和 Task.Factory.StartNew ...

  4. C语言task的用法,C# Task 用法

    C# Task 的用法 其实Task跟线程池ThreadPool的功能类似,不过写起来更为简单,直观.代码更简洁了,使用Task来进行操作.可以跟线程一样可以轻松的对执行的方法进行控制. 顺便提一下, ...

  5. C语言中task的用法,C# Task详解

    C# Task详解  https://www.cnblogs.com/zhaoshujie/p/11082753.html 1.Task的优势 ThreadPool相比Thread来说具备了很多优势, ...

  6. Task.Run vs Task.Factory.StartNew

    Task.Run 和 Task.Factory.StartNew 都可以把一段要执行的代码放到ThreadPool thread中去执行.Task.Factory.StartNew是.Net 4.0中 ...

  7. 单线程任务 Task.Factory.StartNew 封装

    代码: using log4net; using SunCreate.CombatPlatform.Security; using System; using System.Collections.G ...

  8. Task.Run Vs Task.Factory.StartNew z

    在.Net 4中,Task.Factory.StartNew是启动一个新Task的首选方法.它有很多重载方法,使它在具体使用当中可以非常灵活,通过设置可选参数,可以传递任意状态,取消任务继续执行,甚至 ...

  9. C# 使用Task.Factory.FromAsync将IAsyncResult、awit结合

    最近在做读写示波器的工作,使用同步去读写示波器的话会阻塞线程,页面假死,这不能忍.然后改为异步,使用各种BeginXX和EndXX方法.由于那项目和示波器通信是有流程的,比如说先做事1,事1做完再做事 ...

最新文章

  1. 34. Search for a Range
  2. 《深入理解Android:卷III A》一一2.4本章小结
  3. Unity Hub安装Android Build Support报错:Failed to delete old Unity Android Supprtinstallation files
  4. 三维触控测试软件,10 条小技巧,告诉你 iPhone XS Max 的三维触控功能怎么用
  5. Python 之内置函数和匿名函数
  6. python输入生日判断星座_用java编一个程序能通过用户输入的生日判断用户的星座。请大神们给点提示或者思路吧。规定不能自定义方法...
  7. 在周二正式发售前 新款MacBook Pro已开始向客户发货
  8. python 网页调试_使用Django 2.0构建Python Restful Web服务:七)在浏览器中浏览和调试restful接口...
  9. kinect相机标定参考教程
  10. 六十星系之03廉贞天府坐辰戌
  11. 捆绑影视IP,玩跨界营销,你真学不会!
  12. CCIG:智能文档处理「新未来」
  13. IOS苹果ipa重签名工具(苹果签名工具,ios签名工具,支持Windows系统和Macos系统)
  14. 神经系统的解剖学基础是,神经系统系统解剖学
  15. 借助CatGPT让turtlesim小乌龟画曲线
  16. java web中的service,servlet和Dao有什么区别
  17. 云计算存储之Ceph是什么?
  18. Android Weekly #31:你最能影响「他者」的,是你正在工作的状态
  19. idea中java文件左下角出现小黄J以及所有注解报红处理
  20. 新浪微博的XSS攻击

热门文章

  1. Windows 8.1 新增控件之 CommandBar
  2. Android窗口管理服务WindowManagerService的简要介绍和学习计划
  3. 将Linux加入Windows域
  4. delphi 算术溢出解决方法_性能优化系列:JVM 内存划分总结与内存溢出异常详解分析...
  5. 在deepin上安装YouCompleteMe
  6. NppFTP小插件的使用
  7. GitHub项目管理维护实用教程
  8. Appium同时运行多个设备
  9. JavaScript全面学习(中阶)
  10. operation 多线程