我对使用async修饰符进行异步编程并不熟悉。我试图弄清楚如何确保我的控制台应用程序的主要方法实际上是异步运行的。
class Program
{
static void Main(string[] args)
{
Bootstrapper bs = new Bootstrapper();
var list = bs.GetList();
}
}
public class Bootstrapper {
public async Task<List<TvChannel>> GetList()
{
GetPrograms pro = new GetPrograms();
return await pro.DownloadTvChannels();
}
}
我知道这不是从“顶层”异步运行的。由于不可能在Main方法上指定异步修饰符,我如何在Main中异步运行代码?
在c# 7.1中,你将能够做一个适当的异步Main。Main方法的适当签名已扩展为:
public static Task Main();
public static Task<int> Main();
public static Task Main(string[] args);
public static Task<int> Main(string[] args);
例如,你可以这样做:
static async Task Main(string[] args)
{
Bootstrapper bs = new Bootstrapper();
var list = await bs.GetList();
}
在编译时,异步入口点方法将被转换为调用GetAwaitor(). getresult()。
详细信息:https://blogs.msdn.microsoft.com/mazhou/2017/05/30/c-7-series-part-2-async-main。
编辑:
要启用c# 7.1语言特性,您需要在项目上右键单击“Properties”,然后转到“Build”选项卡。在那里,点击底部的高级按钮:
从语言版本下拉菜单中,选择“7.1”(或更高的值):
默认是“最新的主要版本”,它将评估(在撰写本文时)c# 7.0,在控制台应用程序中不支持async main。
我将添加一个所有其他答案都忽略了的重要功能:取消。
TPL的一大特点是支持取消功能,控制台应用有内置的取消功能(CTRL+C)。把它们结合在一起很简单。这是我如何构建所有异步控制台应用程序:
static void Main(string[] args)
{
CancellationTokenSource cts = new CancellationTokenSource();
System.Console.CancelKeyPress += (s, e) =>
{
e.Cancel = true;
cts.Cancel();
};
MainAsync(args, cts.Token).GetAwaiter.GetResult();
}
static async Task MainAsync(string[] args, CancellationToken token)
{
...
}
如果你使用的是c# 7.1或更高版本,使用nawfal的答案,只需将Main方法的返回类型更改为Task或Task<int>。如果你不是:
有一个像Johan说的异步任务MainAsync。
调用它的. getawaiter (). getresult()来捕获像do0g所说的底层异常。
像科里说的那样取消支持。
第二个CTRL+C应该立即终止该进程。(谢谢binki !)
处理OperationCancelledException -返回适当的错误码。
最终代码如下:
private static int Main(string[] args)
{
var cts = new CancellationTokenSource();
Console.CancelKeyPress += (s, e) =>
{
e.Cancel = !cts.IsCancellationRequested;
cts.Cancel();
};
try
{
return MainAsync(args, cts.Token).GetAwaiter().GetResult();
}
catch (OperationCanceledException)
{
return 1223; // Cancelled.
}
}
private static async Task<int> MainAsync(string[] args, CancellationToken cancellationToken)
{
// Your code...
return await Task.FromResult(0); // Success.
}