Task.Factory.StartNewTResult 和 Task.RunTResult 到底有什么区别?

前言

这不是和《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>>:

03499c9d5293e861aef186ac782889fd.png

这是为什么呢?

原理

其实是因为上述代码传入的参数类型不是 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“

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/289189.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大数据服务社会的一个有益实践

自从有了微信&#xff0c;很多人的生活习惯就发生了不同以往的变化。比如&#xff0c;早上起床后的第一件事&#xff0c;可能就是把积压的未读微信信息快速浏览一遍&#xff0c;该发的发、该转的转。笔者虽离开工作岗位&#xff0c;却依然总有时间不够用的感觉&#xff0c;所以…

python pysnmp使用

SNMP标准引入一组ASN.1语言元素&#xff0c;称之为SMI&#xff08;Structure of Management Information&#xff09;。由SMI描述的相互关联的被管对象&#xff08;Managed Objects&#xff09;组成MIB&#xff08;Management Information Base&#xff09;模块。核心MIB中经常…

Git之checkout到别的分支提示Your local changes to the following files would be overwritten by checkout:

1 问题 在我自己的分支,然后切换到主分支,提示错误如下 Your local changes to the following files would be overwritten by checkout:****file****file 2 解决办法 先把这些文件进行add操作,然后再进行commit,就可以了, git add filegit commit -m commit message 然后你…

javaweb连接不上mysql怎么办_java web应用连接mysql会突然connection连接失败

tomcat6.0mysql5.1项目&#xff1a;java web项目问题&#xff1a;原本项目运行了好几天了&#xff0c;一直没发现问题&#xff0c;突然今天报数据库连接异常&#xff0c;进入看日志发现### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransien…

【遥感物候】C#遥感数据GIMMS 3G NDVI头文件批量生成器(几何校正)

长时间序列全球NDVI数据GIMMS 3g(点击下载),原数据无投影,格式为VI3g,IE浏览器下载的为.txt格式。GIS软件无法直接打开,Envi 5可以打开。 ENVI中点击File->Open File as->Binary会弹出填写元数据的窗口,填写基本信息: Envi5.1中打开二进制(Binary)数据是,需要…

Kuzzle,一种内部部署的文档后端

Kuzzle是一种可以内部部署或是在云中运行的文档后端。在近期的CES 2017上&#xff0c;提供该平台的公司公布了其企业版解决方案。 Kuzzle用NoSQL仓库对文档做持久保存&#xff0c;支持基于模式的或是无模式的文档。Kuzzle提供CRUD API&#xff0c;并使用了Elasticsearch提供高级…

分享一个基于.NET6包含DDD,ES,CQRS等概念的开源项目

当你在学习DDD、CQRS或时间溯源时&#xff0c;除了大量的学习资源&#xff08;比如书籍和文章&#xff09;之外&#xff0c;你还接触到了许多概念&#xff0c;这些资源只是在讨论理论问题。这很好&#xff0c;我们知道他们在说什么&#xff0c;但我们如何在一个真正的项目中使用…

React Native之通过createStackNavigator实现携带参数的页面与页面之间的跳转

1 实现的功能 在网上看React Native文档,我特码就想实现一个页面到另外一个页面的跳转,然后另外一个页面怎么获取参数,特么没找到一个说清楚的,要么太复杂,要么说了不理解,下面是我自己写的一个App.js文件,实现一个Home页面跳到另外Details页面,并且携带了参数怎么在Details页…

google浏览器插件 开发 获取页面指定数据_程序员必备的4款Chrome插件,编程神器...

一直有粉丝留言&#xff0c;想要大侠推荐几款程序员使用的插件&#xff0c;大侠特意去问了隔壁的程序员哥哥&#xff0c;终于被我问出了这4款编程神器&#xff01;这4款插件不仅仅是提高效率那么简单哦&#xff0c;还可以让你的Chrome浏览器变得高端大气&#xff0c;一起来看看…

强制类型转换问题

在c中&#xff0c;当把一个表示范围更大的类型的数值a赋值给一个表示范围更小的类型时&#xff0c;会自动进行强制类型转换&#xff0c;转化为范围表示更大的类型。 转换的规律是&#xff0c;这里假定较小的类型表示的数值的个数为n。转化后的值为a模n后的余数。 对于整型数a&a…

MATLAB多元非线性回归

解释变量&#xff1a;商品价格&#xff08;x1&#xff09;人均月收入&#xff08;x2&#xff09;&#xff0c;被解释变量&#xff1a;商品需求量&#xff08;y&#xff09;&#xff0c;进行二元回归分析&#xff0c;并进行检验 商品价格(元/件) 月收入(元) 需求(件) 89 …

媒体应用大数据,先解决三大难题

在大数据时代&#xff0c;互联网是骨骼&#xff0c;大数据则是血液。大数据的核心在于数据&#xff0c;具有海量、高频、在线、实时等特点&#xff0c;但是对于传统媒体来说&#xff0c;在运用大数据的过程中&#xff0c;存在着数据资源不足、数据平台欠缺和缺乏有竞争力的数据…

mysql之主从复制 简书_MySQL主从复制(传统)

拓扑结构&#xff1a;(一主多从)Mysql-master01 (192.168.43.123)Mysql-slave01 (192.168.43.124)Mysql-slave02 (192.168.43.125)版本信息&#xff1a;OS版本 &#xff1a; CentOS release 6.10 最小化安装Mysql版本&#xff1a; mysql-5.7.31-1.el6.x86_64.rpm…

.NET高级调试 | 通过JIT拦截无侵入调试 C# Emit 生成的动态代码

大家还记得上一篇的测试代码吗&#xff1f;我们用了&#xff1a;Console.WriteLine("Function Pointer: 0x{0:x16}", Marshal.GetFunctionPointerForDelegate(addDelegate).ToInt64());来获得 委托 的 函数指针 地址&#xff0c;通过这个突破口最终实现了 动态代码 的…

linux之eval命令

1 eval命令 eval命令将会首先扫描命令行进行所有的替换&#xff0c;类似于C语言中的宏替换&#xff0c;然后再执行命令,该命令使用于那些一次扫描无法实现其功能的变量。该命令对变量进行两次扫描. 2 测试使用 ~$ echo chenyu > 1.txt ~$ puts"cat 1.txt" ~$ ev…

ArrayList用法说明

System.Collections.ArrayList类是一个特殊的数组。通过添加和删除元素,就可以动态改变数组的长度。 一.优点 1。支持自动改变大小的功能 2。可以灵活的插入元素 3。可以灵活的删除元素 二.局限性 跟一般的数组比起来,速度上差些

[译] ASP.NET 生命周期 – ASP.NET 上下文对象(八)

使用 HttpResponse 对象 HttpResponse 对象是与 HttpRequest 对象相对应的&#xff0c;用来表示构建中的响应。它当中提供了方法和属性可供我们自定义响应&#xff0c;有一些在使用 MVC 视图的时候很少使用到&#xff0c;但是在使用其他组件的时候可能十分有用&#xff0c;比如…

使用IAR开发CC2530遇到的两个问题

2019独角兽企业重金招聘Python工程师标准>>> 首先说明&#xff0c;IAR for 8051为7.51版本&#xff0c;操作系统为windows7 32位。 上手CC2530&#xff0c;在IDE的使用上就遇到了2个问题。 一个是用SmartRF Programmer Flash下载HEX文件不成功&#xff0c;提示说cou…

openssh登陆时提示服务器拒绝了密码

升级openssh7.5后&#xff0c;登陆报错按照网上的说法是不允许root用户登陆但是&#xff0c;/etc/ssh/sshd_config 已经写入PermitRootLogin yes解决方法&#xff1a;设置/etc/sysconfig/selinux 中的SELINUXdisabled然后重启就OK了转载于:https://blog.51cto.com/adamcrab/194…

js监听地址栏变化_vue中本地储存也可以实时监听

网上看到的这个方法 在项目里使用了 贼爽啊&#xff0c;分享下顺便说一下 localStorage也实用比如 在同一个页面里边 不同位置 两个变量的呈现都是使用的本地储存且一个变量修改&#xff0c;第二个变量也要实时变化 在正常情况下 修改一个的值后储存起来 在不刷新页面的情况下 …