The default ASP.NET Core templates contain the following Main
method:
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
That Run
method there is the WebHostExtensions.Run
extension method which is implemented like this:
public static void Run(this IWebHost host)
{
host.RunAsync().GetAwaiter().GetResult();
}
So this actually calls WebHostExtensions.RunAsync
, and just blocks on it.
Now, let’s look at how C# 7.1’s asynchronous Main
method is specified:
When one of [these task-based methods] is identified as the entrypoint, the compiler will synthesize an actual entrypoint method that calls one of these coded methods:
static Task Main()
will result in the compiler emitting the equivalent ofprivate static void $GeneratedMain() => Main().GetAwaiter().GetResult();
static Task Main(string[])
will result in the compiler emitting the equivalent ofprivate static void $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();
So basically, having an asynchronous Main
method like this:
public static async Task Main(string[] args)
{
await BuildWebHost(args).RunAsync();
}
Will cause the compiler to also emit the following:
private static void $GeneratedMain(string[] args)
{
Main(args).GetAwaiter().GetResult();
}
And if you look close at what happens with the returned task there, this is pretty much the exact same thing as what the WebHostExtensions.Run
method does.
So what does this mean? You can use either of these solutions and the effect will be the same. Your application will properly block until the asynchronous task gets resolved. There is no practical difference between the solutions. The only real benefit you would have from using an asynchronous main method would be if you had other asynchronous work to do in the Main
method; although this would likely be very rare case since for web applications, you are more likely to do setup work within the lifecycle of the ASP.NET Core application (i.e. in Startup
, and not outside of it).