As you discovered, in VS11 the compiler will disallow an async Main method. This was allowed (but never recommended) in VS2010 with the Async CTP.

I have recent blog posts about async/await and asynchronous console programs in particular. Here's some background info from the intro post:

If "await" sees that the awaitable has not completed, then it acts asynchronously. It tells the awaitable to run the remainder of the method when it completes, and then returns from the async method. Await will also capture the current context when it passes the remainder of the method to the awaitable.

Later on, when the awaitable completes, it will execute the remainder of the async method (within the captured context).

Here's why this is a problem in Console programs with an async Main:

Remember from our intro post that an async method will return to its caller before it is complete. This works perfectly in UI applications (the method just returns to the UI event loop) and ASP.NET applications (the method returns off the thread but keeps the request alive). It doesn't work out so well for Console programs: Main returns to the OS - so your program exits.

One solution is to provide your own context - a "main loop" for your console program that is async-compatible.

If you have a machine with the Async CTP, you can use GeneralThreadAffineContext from My Documents\Microsoft Visual Studio Async CTP\Samples(C# Testing) Unit Testing\AsyncTestUtilities. Alternatively, you can use AsyncContext from my Nito.AsyncEx NuGet package.

Here's an example using AsyncContextGeneralThreadAffineContext has almost identical usage:

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();
}
}

Alternatively, you can just block the main Console thread until your asynchronous work has completed:

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();
}
}

Note the use of GetAwaiter().GetResult(); this avoids the AggregateException wrapping that happens if you use Wait() or Result.

Update, 2017-11-30: As of Visual Studio 2017 Update 3 (15.3), the language now supports an async Main - as long as it returns Task or Task<T>. So you can now do this:

class Program
{
static async Task Main(string[] args)
{
Bootstrapper bs = new Bootstrapper();
var list = await bs.GetList();
}
}

The semantics appear to be the same as the GetAwaiter().GetResult() style of blocking the main thread. However, there's no language spec for C# 7.1 yet, so this is only an assumption.

https://stackoverflow.com/questions/9208921/cant-specify-the-async-modifier-on-the-main-method-of-a-console-app

C# Main函数中调用异步方法的2种实现的更多相关文章

  1. java中main函数怎么调用外部非static方法

    使用外部方法时(不管是static还是非static),都要先new一个对象,才能使用该对象的方法. 举例如下: 测试函数(这是错误的): public class Test { public sta ...

  2. eclipse 中main()函数中的String[] args如何使用?通过String[] args验证账号密码的登录类?静态的主方法怎样才能调用非static的方法——通过生成对象?在类中制作一个方法——能够修改对象的属性值?

    eclipse 中main()函数中的String[] args如何使用? 右击你的项目,选择run as中选择 run configuration,选择arguments总的program argu ...

  3. 在信号处理函数中调用longjmp

    错误情况及原因分析 前两天看APUE的时候,有个程序要自己制作一个sleep程序,结果在这个程序中就出现了在信号处理函数中调用longjmp函数的情况,结果就出现了错误,具体错误是啥呢,请参见下面这段 ...

  4. linux中应用程序main函数中没有开辟进程的,它应该在那个进程中运行呢?

    1.main函数是一个进程还是一个线程? 不知道你是用c创建的,还是用java创建的. 因为它们都是以main()做为入口开始运行的. 是一个线程,同时还是一个进程. 在现在的操作系统中,都是多线程的 ...

  5. (转)Java程序利用main函数中args参数实现参数的传递

    Java程序利用main函数中args参数实现参数的传递 1.运行Java程序的同时,可以通过输入参数给main函数中的接收参数数组args[],供程序内部使用!即当你在Java命令行后面带上参数,J ...

  6. 在类的成员函数中调用delete this

    最近面试的时候被问到一个问题是,在C++中,能否在类的成员函数中调用delete this,后来网上查了一下资料,关于这个问题说得比较好的有http://blog.sina.com.cn/s/blog ...

  7. [原创]C/C++语言中,如何在main.c或main.cpp中调用另一个.c文件

    C/C++语言中,如何在main.cpp中调用另一个.c文件主要有5种思路: 1.在VS2012 IDE中,将被引用的.c文件后缀名全部修改为.h,然后通过IDE的解决方案资源管理器中鼠标右键单击“头 ...

  8. 问题:C#控制台程序参数;结果:设置与读取C#控制台应用程序Main函数中的参数args

    设置与读取C#控制台应用程序Main函数中的参数args 在项目属性面版->调试->命令行参数设置.空格分隔.读取:string[] str = Environment.GetComman ...

  9. .NET中如何在同步代码块中调用异步方法

    更新记录 本文迁移自Panda666原博客,原发布时间:2021年7月2日. 在同步代码块中调用异步方法,方法有很多. 一.对于有返回值的Task 在同步代码块中直接访问 Task 的 Result ...

随机推荐

  1. Java中BigDecimal的舍入模式

    java.math.BigDecimal 不可变的.任意精度的有符号十进制数.BigDecimal 由任意精度的整数非标度值和32位的整数标度(scale)组成. 如果为零或正数,则标度是小数点后的位 ...

  2. 备忘:移植ucos-III到stm32f103c8t6

    由于本人对linux系统内核这块比较感兴趣,下一份工作想做linux驱动相关的:于是最近一旦有空都在研究linux内核源码,面对linux内核这个庞然大物,越看越觉得不能太过急躁,且由于还要工作,只能 ...

  3. k-近邻法(kNN)

    原理: 已知一个训练样本集(有标签),计算待测试样本与所有训练样本的距离. 按距离从小到大进行排序并取前 k 个,统计 k 个中出现次数最多的分类为分类结果. 优点:精度高,对异常值不敏感,无数据输入 ...

  4. mysql密码遗失

    仅以本地数据库测试 本地数据库密码遗失,百度上的方法很麻烦,想着没有用的一个本地库(localhost),就想删库重建,navicat上点击数据库,删除链接.然后在新建库,同名同端口的,此时密码已经制 ...

  5. 我是如何通过学习拿到年薪80w

    本人做了5年Java,如今还是一个码农,天天写业务代码,直到2018年10月中旬遇到一位技术大牛,他给我一套技术思维导图让我又看到了希望!今天分享给各位想要提升.升职.加薪的你. 普通Java程序员与 ...

  6. 使用线程操作刷新Winform界面

    主窗体中添加代码 public FrmMain() { InitializeComponent(); System.Threading.Thread thread = new System.Threa ...

  7. 五、Vi和Vim编辑器

    1. Vim编辑器: 在Linux下一般使用vi编辑器来编辑文件.vi既可以查看文件也可以编辑文件.三种模式: 命令行.插入.底行模式 切换到命令行模式:按Esc键: 切换到插入模式:按 i .o.a ...

  8. 常见IO模型

    在socket的通信中,recv,accept,recvfrom(UDP协议接收信息)这些阶段由于需要收到信息,才能继续下面的代码,所以这些阶段叫做阻塞,类似于我们python变成中的input函数, ...

  9. POJ - 3264——Balanced Lineup(入门线段树)

    Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 68466   Accepted: 31752 ...

  10. grep用法

    正则表达式只是一种表示法,只要工具支持这种表示法, 那么该工具就可以处理正则表达式的字符串.vim.grep.awk .sed 都支持正则表达式,也正是因为由于它们支持正则,才显得它们强大:在以前上班 ...