TPL 和 async/await 之间的区别(线程处理)

     2023-03-07     121

关键词:

【中文标题】TPL 和 async/await 之间的区别(线程处理)【英文标题】:Difference between the TPL & async/await (Thread handling) 【发布时间】:2012-05-04 08:05:19 【问题描述】:

在线程创建方面尝试了解 TPL 和 async/await 之间的区别。

我相信 TPL (TaskFactory.StartNew) 的工作方式类似于 ThreadPool.QueueUserWorkItem,因为它在线程池中的线程上排队工作。当然,除非您使用 TaskCreationOptions.LongRunning 创建一个新线程。

我认为async/await 的工作原理与此类似:

TPL:

Factory.StartNew( () => DoSomeAsyncWork() )
.ContinueWith( 
    (antecedent) => 
        DoSomeWorkAfter(); 
    ,TaskScheduler.FromCurrentSynchronizationContext());

Async/Await:

await DoSomeAsyncWork();  
DoSomeWorkAfter();

将是相同的。从我一直在阅读的内容来看,async/await 似乎只有“有时”会创建一个新线程。那么它什么时候创建一个新线程,什么时候不创建一个新线程呢?如果您正在处理 IO 完成端口,我可以看到它不必创建新线程,否则我认为它必须这样做。我想我对FromCurrentSynchronizationContext 的理解也总是有点模糊。我一直认为它本质上是 UI 线程。

【问题讨论】:

实际上,TaskCreationOptions.LongRunning 并不能保证“新线程”。根据 MSDN,“LongRunning”选项仅向调度程序提供提示;它不保证有一个专用线程。我发现了这个困难的方式。 @eduncan911 尽管您对文档的看法是正确的,但我不久前查阅了 TPL 源代码,我很确定实际上在 TaskCreationOptions.LongRunning 时总是会创建一个新的专用线程已指定。 @ZaidMasud:你可能想再看看。我知道它正在合并线程,因为 Thread.CurrentThread.IsThreadPoolThread 对于几百毫秒的短时间运行线程返回 true。更不用说我使用的 ThreadStatic 变量渗入多个线程,导致各种破坏。我不得不强制我的代码新建多个 Thread(),这是老式的方式,以保证专用线程。换句话说,我不能将 TaskFactory 用于专用线程。或者,您可以实现自己的 TaskScheduler,它始终返回一个专用线程。 【参考方案1】:

我相信 TPL (TaskFactory.Startnew) 的工作方式与 ThreadPool.QueueUserWorkItem 类似,因为它将线程池中线程上的工作排队。

Pretty much.

从我一直在阅读的内容来看,async/await 似乎只是“有时”会创建一个新线程。

实际上,它从来没有。如果你想要多线程,你必须自己实现它。有一个新的Task.Run 方法,它只是Task.Factory.StartNew 的简写,它可能是在线程池上启动任务的最常用方法。

如果您正在处理 IO 完成端口,我可以看到它不必创建新线程,否则我认为它必须这样做。

宾果游戏。所以像 Stream.ReadAsync 这样的方法实际上会在 IOCP 周围创建一个 Task 包装器(如果 Stream 有一个 IOCP)。

您还可以创建一些非 I/O、非 CPU 的“任务”。一个简单的例子是Task.Delay,它返回一个在一段时间后完成的任务。

async/await 很酷的一点是,您可以将一些工作排​​队到线程池(例如,Task.Run),执行一些 I/O 绑定操作(例如,Stream.ReadAsync),以及做一些其他操作(例如,Task.Delay)......它们都是任务!它们可以被等待或组合使用,例如Task.WhenAll

任何返回Task 的方法都可以是awaited - 它不必是async 方法。所以Task.Delay 和 I/O 绑定操作只需使用TaskCompletionSource 来创建和完成任务——线程池上唯一要做的就是事件发生时的实际任务完成(超时、I/O 完成等) )。

我想我对 FromCurrentSynchronizationContext 的理解也总是有点模糊。我一直认为它本质上是 UI 线程。

我在SynchronizationContext 上写了an article。大多数时候,SynchronizationContext.Current

如果当前线程是 UI 线程,则为 UI 上下文。 如果当前线程正在为 ASP.NET 请求提供服务,则为 ASP.NET 请求上下文。 否则是线程池上下文。

任何线程都可以设置自己的SynchronizationContext,所以上面的规则也有例外。

注意默认的Task awaiter 会在当前SynchronizationContext 上调度async 方法的剩余部分如果它不为空;否则它将继续当前的TaskScheduler。这在今天并不那么重要,但在不久的将来它将是一个重要的区别。

我在博客上写了自己的async/await intro,Stephen Toub 最近发布了一个出色的async/await FAQ。

关于“并发”与“多线程”,请参阅this related SO question。我想说async 启用并发,这可能是也可能不是多线程的。使用await Task.WhenAllawait Task.WhenAny 做并发处理很容易,除非你显式使用线程池(例如Task.RunConfigureAwait(false)),那么你可以同时进行多个并发操作(例如,多个 I/O 或其他类型,如 Delay) - 它们不需要线程。对于这种情况,我使用术语“单线程并发”,尽管在 ASP.NET 主机中,您实际上可以得到“-线程并发”。这很甜蜜。

【讨论】:

不错的答案。我还推荐infoq.com/articles/Async-API-Design 和这个出色的演示:channel9.msdn.com/Events/TechEd/Europe/2013/DEV-B318。 第一个链接失效了。 “async/await FAQ”链接失效 是的。微软移动了一堆东西,并破坏了几乎所有指向其内容的链接。此答案接受 PR。【参考方案2】:

async / await 基本上简化了ContinueWith 方法(在Continuation Passing Style 中继续)

它没有引入并发——你仍然需要自己做(或者使用框架方法的异步版本。)

因此,C# 5 版本将是:

await Task.Run( () => DoSomeAsyncWork() );
DoSomeWorkAfter();

【讨论】:

那么在我上面的示例中,它在哪里运行 DoSomeAsyncWork(异步/等待版本)?如果它在 UI 线程上运行,它如何不阻塞? 如果 DoSomeWorkAsync() 返回 void 或不可等待的东西,您的 await 示例将无法编译。从您的第一个示例中,我假设它是您希望在不同线程上运行的顺序方法。如果您将其更改为返回Task,而不引入并发,那么是的,它会阻塞。从某种意义上说,它会按顺序执行,就像 UI 线程上的普通代码一样。 await 仅在方法返回尚未完成的等待时才会产生。 好吧,我不会说它会在它选择运行的任何地方运行。您已使用 Task.Run 执行 DoSomeAsyncWork 中的代码,因此在这种情况下,您的工作将在线程池线程上完成。 我喜欢你的简洁回答。

async/await和promise区别

async/await的优势:可以很好地处理then链对于单一的Promise链其实并不能发现async/await的优势,当需要处理由多个Promise组成的then链的时候,优势就能体现出来了,接下来直接上代码:/***传入参数n,表示这个函数执行的时间(毫秒... 查看详情

async(await)函数和generator函数区别

async函数是Generator函数的语法糖。async函数对Generator函数的改进体现在:1.async内置执行器。Generator函数的执行必须靠执行器,需要调用next()方法,或者用co模块;而async函数自带执行器。也就是说,async函数的执行与普通函数一模一... 查看详情

promise与async和await的区别(代码片段)

...og(awaitgetJSON)return"done"makeRequest()复制代码复制代码区别:  1)函数前面多了一个aync关键字。await关键字只能用在a 查看详情

Async/Await 和 Dispatcher 的区别

】Async/Await和Dispatcher的区别【英文标题】:DifferencebetweenAsync/AwaitandDispatcher【发布时间】:2021-09-2019:57:08【问题描述】:我正在开发一个WPF应用程序,我遇到了冻结问题,现在我知道它是一个单线程应用程序,但我对术语感到困... 查看详情

Callback 函数与 Promise 和 Async await 的区别

】Callback函数与Promise和Asyncawait的区别【英文标题】:differencebetweenCallbackfunctionandPromiseandAsyncawit【发布时间】:2019-09-2520:41:36【问题描述】:我了解回调函数,但我不了解promise方法和async和await。为什么在节点js中使用这三个函数... 查看详情

Task.Start/Wait 和 Async/Await 有啥区别?

】Task.Start/Wait和Async/Await有啥区别?【英文标题】:What\'sthedifferencebetweenTask.Start/WaitandAsync/Await?Task.Start/Wait和Async/Await有什么区别?【发布时间】:2012-03-2003:16:59【问题描述】:我可能遗漏了一些东西,但做这件事有什么区别:pu... 查看详情

promise和async的区别(代码片段)

promisePromise,我们了解到promise是ES6为解决异步回调而生,避免出现这种回调地狱,那么为何又需要Async/Await呢?你是不是和我一样对Async/Await感兴趣以及想知道如何使用,下面一起来看看这篇文章:Async/Await替代Promise的6个理由。... 查看详情

使用 async/await 会创建一个新线程吗?

】使用async/await会创建一个新线程吗?【英文标题】:Doestheuseofasync/awaitcreateanewthread?【发布时间】:2015-01-3116:01:20【问题描述】:我是TPL的新手,我想知道:C#5.0新增的异步编程支持(通过新的async和await关键字)与线程的创建有... 查看详情

nestjs 有或没有 async/await 有区别吗?

...【发布时间】:2020-12-2723:17:04【问题描述】:我认为以下之间没有区别:@Post()saveClient(@Param()params,@Body()createClientDto:ClientDto)this.clientRepository.save( 查看详情

async和await(代码片段)

...上async,该函数就变成了异步函数。该函数和普通函数的区别:异步函数的返回值是一个Promsie对象,相当于返回的值包裹在了Promise.resolve()内进行返回的异步函数内可以使用await关键字async函数内抛出错误,是通过返回值的Promsie... 查看详情

async await task.run xamarin 表单

...描述】:我只是想确保我理解asyncawait和Task.run或Task.whenall之间的区别所以asyncawait就是处理异步方法。这意味着有一个隐含的处理顺序。我在没有阻塞主线程的情况下运行了很长时间,并等待结果继续。对于Task.Run和T 查看详情

async与promise的区别(代码片段)

https://www.jianshu.com/p/51f5fd21588easync/await是基于promise实现的,他不能用于普通的回调函数async/await使得异步代码看起来像同步代码async/await与Promise一样,是非阻塞的。不同函数前面多了一个async关键字。await关键字只能用在async定义... 查看详情

在 Javascript 中的 API 调用之间使用 ASYNC/AWAIT 中的数组方法

】在Javascript中的API调用之间使用ASYNC/AWAIT中的数组方法【英文标题】:UsingArrayMethodinsideASYNC/AWAITbetweenAPIcallsinJavascript【发布时间】:2018-11-2102:56:30【问题描述】:我想让我的代码更具可读性,使用async/await而不是fetch()。我的代码... 查看详情

async,await与task.wait()或task.result的区别(代码片段)

...wait()或者task.Result的区别?接下来,一个Demo让你看出他们之间的区别。staticvoidMain(string[]args)Console.WriteLine("start");Test();//不等待Console.WriteLine("end");Console.Read();staticTask<int>Sleep()Console.WriteLine("Sleepstart");Thread.Sleep(1000);Console.WriteLi... 查看详情

async和await(代码片段)

async和awaitasync的使用await的使用在async和await出来之前,异步回调的方法就有1、回调嵌套2、Promsie的链式回调3、Generator的复杂繁琐调用方式async/await采用同步的思维来解决异步问题的方式,使代码的可读性更强了。async的使... 查看详情

async和await总结

...想要promise,想要promise异步执行的成功的value数据3.哪里写async?await所在函数(最近的)定义的左侧写async 查看详情

async和await(代码片段)

async和awaitAsync/await在NodeJS7.6引入,当前已被所有现代浏览器支持。简介async/await是一种新的使用异步代码的方式,代替之前回调或者promise的方式。是基于promise的语法糖,无法在普通的回调函数中使用,await必须在async方法中调用... 查看详情

async和await

...使用的Thread来使用异步多线程操作,基本上看不见有使用Async、Await进行异步编程的。各有所爱吧,其实都可以。只要正确使用就行,不过还是写了这篇文章推荐大家使用Async、Await。原因就是:可以跟写同步方法一样去异步编程... 查看详情