异步和等待 - 控制台、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 或控制台应用程序中调用 Wait
或 Result
的问题是什么意思......在这两种情况下可能都是必需的,但同样可能不是。这取决于你真正在做什么。不要忘记,即使是控制台应用程序也可以启动自己的线程并执行各种其他操作 - 例如,您可以在控制台应用程序中编写 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 窗体运行的控制台应用程序
Javascript - 异步等待和获取 - 返回值,而不是承诺?