如您所见,在VS11中,编译器将禁止使用
async Main方法。在VS2010中,使用Async CTP允许(但绝不建议这样做)。
我最近在博客文章中特别提到了异步/等待和异步控制台程序。以下是介绍性帖子中的一些背景信息:
如果“ await”看到awaitable尚未完成,则它将异步执行。它告诉等待的对象在完成时运行该方法的其余部分,然后从异步方法中 返回
。当等待方法将其余方法传递给等待方法时,它还将捕获当前 上下文 。稍后,当awaitable完成时,它将执行async方法的其余部分(在捕获的上下文中)。
这就是在控制台程序中使用出现问题的原因
async Main:
请记住,在我们的介绍性帖子中,异步方法将在完成之前 返回
其调用方。这在UI应用程序(该方法仅返回到UI事件循环)和ASP.NET应用程序(该方法从线程返回但使请求保持活动状态)中完美地工作。对于Console程序,效果不是很好:Main返回OS-
因此程序退出。
一种解决方案是提供您自己的上下文-异步兼容的控制台程序的“主循环”。
如果您有一台具有异步CTP的计算机,则可以
GeneralThreadAffineContext从“ 我的文档” “ Microsoft Visual
Studio”中,使用“异步CTP” “样本(C#测试)”单元测试“ AsyncTestUtilities”
。或者,您可以
AsyncContext从我的Nito.AsyncEx
NuGet包中使用。
这是一个使用
AsyncContext; 的例子。
GeneralThreadAffineContext具有几乎相同的用法:
using Nito.AsyncEx;class Program{ static void Main(string[] args) { AsyncContext.Run(() => MainAsync(args)); } static async void MainAsync(string[] args) { Bootstrapper bs = new Bootstrapper(); var list = await bs.GetList(); }}
或者,您可以仅阻塞主控制台线程,直到异步工作完成:
class Program{ static void Main(string[] args) { MainAsync(args).GetAwaiter().GetResult(); } static async Task MainAsync(string[] args) { Bootstrapper bs = new Bootstrapper(); var list = await bs.GetList(); }}
注意使用
GetAwaiter().GetResult();
这样可以避免
AggregateException使用
Wait()或时发生的换行
Result。
更新,2017-11-30: 从Visual Studio 2017更新3(15.3)开始,该语言现在支持
asyncMain-,只要它返回
Task或即可
Task<T>。因此,您现在可以执行以下 *** 作:
class Program{ static async Task Main(string[] args) { Bootstrapper bs = new Bootstrapper(); var list = await bs.GetList(); }}
语义似乎与
GetAwaiter().GetResult()阻塞主线程的样式相同。但是,尚无C#7.1的语言规范,因此这只是一个假设。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)