从来好事天生俭,自古瓜儿苦后甜。这篇文章主要讲述Task.Factory.StartNew<
TResult;
和 Task.Run<
TResult;
到底有什么区别?相关的知识,希望能为你提供帮助。
前言这不是和《??Task.Factory.StartNew 和 Task.Run 到底有什么区别???》一样吗,怎么又写一篇?
起先我也是这么觉得的,但实际发现并非如此。
实现代码【Task.Factory.StartNew<
TResult;
和 Task.Run<
TResult;
到底有什么区别()】查看这 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 hasnt 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“
推荐阅读
- 企业该如何构建智能化敏捷运维体系4.0呢(要点都在这了)
- JDK8中String的intern()方法详细解读内存图解+多种例子+1.1w字长文
- # yyds干货盘点 # Python网络爬虫真实的URL看来真不能光凭着XHR找
- 无需DevEco Studio就能编译OHOS应用
- Kubernetes的安全机制
- sed命令基本使用
- 企业级反向代理HAproxy
- N64025的第一周作业
- 11个最佳Node.js开发IDE推荐下载列表(哪款最好用())