Reputation: 5772
The hosting design in the ASP.NET Core have a new Generic Host now (.NET Core 2.1+) that will replace the Web Host in the future.
There are a lot of ways to start the application using the Microsoft.Extensions.Hosting
interfaces IHost
and IHostBuilder
.
I know the difference between using async
vs sync
, but what are the differences between all these options? Using Run
vs Start
and calling on IHostBuilder
vs calling on IHost
?
See the options // 1
, // 2
, // 3
and // 4
in the code below:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace MyNamespace
{
class Program
{
static async Task Main(string[] args)
{
IHostBuilder builder = CreateBuilder();
// 1 - Call Run on the builder (async)
await builder.RunConsoleAsync(); // extension method
// 2 - Call Start on the builder (sync)
builder.Start(); // extension method
IHost host = builder.Build(); // Call Build on the builder to get a host
// 3 - Call Run on the host (sync / async)
host.Run(); // extension method
await host.RunAsync(); // extension method
// 4 - Call Start on the host (sync / async)
host.Start(); // extension method
await host.StartAsync(); // class method
}
private static IHostBuilder CreateBuilder() => new HostBuilder()
.ConfigureAppConfiguration((hostingContext, config) =>
{
//...
})
.ConfigureLogging((hostingContext, logging) => {
//...
})
.ConfigureServices((hostContext, services) =>
{
//...
services.AddSingleton<IHostedService, MyService>();
});
}
}
Upvotes: 63
Views: 31229
Reputation: 25251
Updated for .NET 6.
RunConsoleAsync
, operate on an IHost
instance. The ones on IHostBuilder
simply call IHost.Build()
and then delegate to the IHost
methods (e.g. IHostBuilder.StartAsync()
is equivalent to IHostBuilder.Build().StartAsync()
)..GetAwaiter().GetResult()
).Task IHost.StartAsync(CancellationToken cancellationToken = default)
Starts the host (web application). Task completes once the host is started.
void Start(this IHost host)
Synchronous wrapper to IHost.StartAync
.
Task RunAsync(this IHost host, CancellationToken token = default)
{
using (host)
{
await host.StartAsync(token);
await host.WaitForShutdownAsync(token);
}
}
Starts the host. Task completes when the host shuts down, which can be trigger by cancelling the token or calling StopAsync()
on another thread.
Task WaitForShutdownAsync(this IHost host, CancellationToken token = default)
Returns a task that completes when the application shuts down. Shutdown is initiated via the passed token, and cancelling the token causes the application to stop.
void WaitForShutdown(this IHost host)
Synchronous wrapper to IHost.WaitForShutdownAync
.
Task IHost.StopAsync(CancellationToken cancellationToken = default)
Gracefully stops the host, returning a task that completes once the host has stopped. Cancelling cancellationToken
indicates stop should no longer be graceful.
There's also an extension method that allows passing a Timeout
instead:
public static Task StopAsync(this IHost host, TimeSpan timeout)
=> host.StopAsync(new CancellationTokenSource(timeout).Token);
Task RunConsoleAsync(this IHostBuilder hostBuilder, CancellationToken cancellationToken = default)
=> hostBuilder.UseConsoleLifetime().Build().RunAsync(cancellationToken);
This is the only one that uses IHostBuilder
(instead of IHost
) because it invokes UseConsoleLifetime()
(which needs IHostBuilder
). This also causes a wait for Ctrl+C to exit.
There's also no corresponding Start method, which I can only speculate is because the vast majority of time in a console app this is all you'd need. The very few that run other backend services plus ASP.NET would probably be better off using RunAsync()
and managing lifetime (ie: controlling the CancellationToken
) themselves.
Upvotes: 62
Reputation: 9165
// 1 - Call Run on the builder (async)
RunConsoleAsync enables console support, builds and starts the host, and waits for Ctrl+C/SIGINT or SIGTERM to shut down. So as it's expected from its name it's for hosting your app in console only (not IIS, etc)
// 2 - Call Start on the builder (sync)
just starts the host synchronously
public static IHost Start(this IHostBuilder hostBuilder)
{
var host = hostBuilder.Build();
host.StartAsync(CancellationToken.None).GetAwaiter().GetResult();
return host;
}
// 3 - Call Run on the host (sync / async)
RunAsync runs the app and returns a Task that completes when the cancellation token or shutdown is triggered. Sync is just a wrapper:
public static void Run(this IHost host)
{
host.RunAsync().GetAwaiter().GetResult();
}
// 4 - Call Start on the host (sync / async)
This method is actually starting the program and it's called eventually from any other ways.
Upvotes: 33