异步和等待 - 控制台、Windows 窗体和 ASP.NET 之间的区别

Posted

技术标签:

【中文标题】异步和等待 - 控制台、Windows 窗体和 ASP.NET 之间的区别【英文标题】:Async and await - difference between console, Windows Forms and ASP.NET 【发布时间】:2020-11-08 05:31:13 【问题描述】:

我一直在自学异步/等待的使用,我想我理解了幕后概念。但是,大多数 Channel 9 教程、MSDN 文章和关于 async/await 的 Stack Overflow 答案都使用基于 GUI 的应用程序(Windows 窗体应用程序)来展示 async/await 的强大功能。

但是,我注意到在基于 UI 线程的应用程序与基于常规 ThreadPool 线程的应用程序(例如 ASP.NET Web 应用程序、控制台应用程序等)中使用 async/await 的根本区别。

由于在基于 UI 线程的应用程序中,UI 线程始终可用(除非进程显式停止或被 Windows 停止),因此负责在任何异步方法中“等待”之后执行代码的 ThreadPool 线程将保证找到 UI 线程以将结果发回(如果有)。

但是,在控制台应用程序或 ASP.NET Web 应用程序中,主线程(在控制台应用程序中)或 HTTP 请求(在 ASP.NET Web 应用程序中)必须等待(在某个时间点),直到所有异步操作完成。所以在 Async 方法调用之后应该有 .Wait() 和 .Result 调用,如果没有更多工作要做的话。

这种理解正确吗?我并不质疑为 I/O 绑定或网络绑定操作使用异步的好处(我了解它将如何提高应用程序的可扩展性)。

【问题讨论】:

可能值得注意的是async and await keywords don't cause additional threads to be created. 在 ASP.Net 和异步上 - 查看 Using Asynchronous Methods in ASP.NET MVC - 所有适当的等待已经为您准备好,您自己的代码不需要调用 Wait/Result。跨度> @AlexeiLevenkov - 在 MVC 中(也在 Windows 窗体应用程序、ASP.NET Web 窗体应用程序中)有一种方法可以使事件处理程序“异步”并且 .NET 框架知道等待一些异步操作要完成。在控制台应用程序中,主线程不能是异步的,它必须等待一些异步操作(甚至是触发和忘记类型的异步操作)在返回之前完成。 【参考方案1】:

由于在基于 UI 线程的应用程序中,UI 线程始终可用(除非进程显式停止或被 Windows 停止),因此负责在任何异步方法中“等待”之后执行代码的 ThreadPool 线程将保证找到 UI 线程来发回结果(如果有的话)。

这有点混乱。没有迹象表明需要 ThreadPool 线程。

由可等待的实现来确定在哪里运行延续,但通常使用当前的同步上下文来确定在哪里运行它:

在控制台应用程序中,没有同步上下文,因此线程池线程用于继续。 在 Windows 窗体应用程序中,当您在 UI 线程上运行时,同步上下文是一个将在 UI 线程上执行代码的上下文...所以继续执行在那里(除非您使用 ConfigureAwait 等。 .) 在 ASP.NET 应用程序中,有一个特定于 ASP.NET 本身的同步上下文。

更多详情请见Stephen Cleary's MSDN article。

不清楚你后面关于必须在 ASP.NET 或控制台应用程序中调用 WaitResult 的问题是什么意思......在这两种情况下可能都是必需的,但同样可能不是。这取决于你真正在做什么。不要忘记,即使是控制台应用程序也可以启动自己的线程并执行各种其他操作 - 例如,您可以在控制台应用程序中编写 HTTP 服务器...

【讨论】:

+1。旁注:我认为在常规控制台应用程序中(没有计时器/消息循环/无限等待)将(应该)至少有一个 Wait/Result 因为 main 是同步的并且需要等待异步操作的完成。事实上,如果控制台应用程序中使用了其他机制(事件、计时器,甚至Sleep...)来确保异步方法的执行完成,则不需要Wait/Result @AlexeiLevenkov:可能有——也可能没有。这真的取决于你想要做什么。我不喜欢在没有更多上下文的情况下发表太多笼统的陈述。 谢谢乔恩!在我的情况下需要等待/结果,因为在调用它正在使用的程序集的异步方法之后,主方法没有任何其他工作要做。在 Windows 窗体应用程序甚至 ASP.NET Web 窗体应用程序中不会出现这种情况,因为事件处理程序可以是异步的(或者可以使用 RegisterAsyncTask)。 @JonSkeet People require 官方 sources 用于“在控制台应用程序中,没有同步上下文”。我在文档中找不到任何具体的内容,您是否知道得更好? @GSerg:另请注意,SynchronizationContext documentation 明确引用了我在此答案中链接到的 MSDN 文章。

以上是关于异步和等待 - 控制台、Windows 窗体和 ASP.NET 之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

将多个参数传递给从 Windows 窗体运行的控制台应用程序

MVC 4 控制器中的异步和等待

如何使用异步发布并使用 HttpClient 等待

Javascript - 异步等待和获取 - 返回值,而不是承诺?

WindowsApplication和ConsoleApplication有啥区别

将异步数据从网页传递到我的窗体 C# .NET 应用程序