你大概知道,C#语言可以构建两种程序。一种是带有入口点(entrypoint)的程序,这样操作系统就可以加载程序并从入口点执行;另一个是没有入口点的程序。操作系统不能直接执行程序,程序可以被其他有入口点的程序引用,这样就可以执行其中的代码。
必须有入口点的应用程序类型有:Windows Forms应用程序、UWP应用程序、控制台应用程序、WPF应用程序、ASP.NET和ASP.NET Core应用程序和Xamarian App。
不需要入口点的应用程序类型有:类库(/t:lib)、模块(/t:module)。
Main方法
像其他语言一样,C#程序从Main方法开始。有四个重载被认为是Main方法的有效签名。
public static void Main(); public static int Main(); public static void Main(string[] args); public static int Main(string[] args);
C#的入口点方法必须是静态的,方法名必须是Main,这个方法的返回类型可以是void或者int,它可以有一个字符串数组的参数,包含任何命令行参数。
如果入口点方法返回一个int值,那么操作系统或使用此入口点启动程序的宿主进程可以评估这个返回值,这在本机环境(译注:与.NET的托管环境相对应)中广泛使用(比如表示外部应用程序的成功启动)。
异步的Main方法
C#在5.0版本(.NET Framework 4.5)中引入了异步/等待模式,使得异步操作的流程易于读懂。许多现有的,为那些异步操作(又名异步编程模型)设计的语言结构可以使用新的async/await关键字。今天,社区开发的许多类库只提供了异步版本的操作。(例如,System.Net.HttpClient, Microsoft.Azure.EventHub.Core.)
正如我在前面所提到的,如果你想在Main方法中等待异步操作,你需要应用一些变通方法,因为下面的Main方法定义是无效的(译注:在C#7.1之前的版本):
public static async Task Main(string[] args) { await BuildWebHost(args).RunAsync(); }
变通的办法是使用同步等待操作。
public static void Main(string[] args) { BuildWebHost(args).RunAsync().GetAwaiter().GetResult(); }
或者调用定义在Task的Wait()方法:
public static void Main(string[] args) { BuildWebHost(args).RunAsync().Wait(); }
在C# 7.1中,C#扩展了Main方法的有效签名,允许这些Main法的异步重载有效。
public static void Main(); public static int Main(); public static void Main(string[] args); public static int Main(string[] args); public static Task Main(); public static Task<int> Main(); public static Task Main(string[] args); public static Task<int> Main(string[] args);
类Task的返回类型允许在Main方法使用async修饰符来实现await关键字。
结论
异步的Main方法使得入口点方法中的异步操作更容易使用,而不需要像在其他异步方法中运行那样使用任何变通方法。在代码编译的时候,任何异步Main方法都将被包装成一个可以被CLR宿主接受的非异步Main方法。由于这个新特性不需要CLR代码更改,所以异步Main方法其实只是一个语法糖。这样的设计允许后端与C#以前的版本兼容。要阅读更多的细节,请参阅Roslyn(译注:C#编译器)源代码仓库里的一篇文章:Aysnc Main。
系列:
[译]C# 7系列,Part 1: Value Tuples
原文:https://www.cnblogs.com/wenhx/p/csharp-7-series-part-2-async-main.html