Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IWebHost: Calling Run() vs RunAsync()

When a new ASP.NET Core 2.0 project is created, the boilerplate Main method in the Program class looks something like this:

public static void Main(string[] args) {     BuildWebHost(args).Run(); // BuildWebHost returns an IWebHost } 

But since C# 7.1, the Main method can be an asynchronous method returning Task instead of void. This means it's much easier to call an async method inside Main.

So the RunAsync() on IWebHost can be called inside Main instead of the Run() method. Something like this:

public static async Task Main(string[] args) {     await BuildWebHost(args).RunAsync().ConfigureAwait(false); } 

According to the documentation, the Run method:

Runs a web application and block the calling thread until host shutdown.

Whereas the RunAsync method:

Runs a web application and returns a Task that only completes when the token is triggered or shutdown is triggered.

I was wondering when should the RunAsync method be used instead of the regular Run method? What are the practical implications of this? Would the end-user notice any difference?

like image 854
Ali Zahid Avatar asked Jan 26 '18 03:01

Ali Zahid


People also ask

What is IWebHost in .NET core?

The IWebHost is the core of your ASP.NET Core application, containing the application configuration and the Kestrel server that listens for requests and sends responses.


2 Answers

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 of private static void $GeneratedMain() => Main().GetAwaiter().GetResult();
  • static Task Main(string[]) will result in the compiler emitting the equivalent of private 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).

like image 116
poke Avatar answered Sep 17 '22 04:09

poke


What are the practical implications of this? Would the end-user notice any difference?

There is no difference on RunTime level behavior.

Since this feature does not correspond to a CLR code change, the async Main method is just a syntactical sugar. This design allows backend compatibility with the previous versions of the language. To read more details, please see Async Main in the Roslyn Git repo.
- C# 7 Series, Part 2: Async Main

like image 29
idubnori Avatar answered Sep 21 '22 04:09

idubnori