IWebHost: вызов Run() против RunAsync()
Когда создается новый проект ASP.NET Core 2.0, шаблон Main
метод в Program
класс выглядит примерно так:
public static void Main(string[] args)
{
BuildWebHost(args).Run(); // BuildWebHost returns an IWebHost
}
Но так как C# 7.1, Main
Метод может быть асинхронным методом, возвращающим Task
вместо void
, Это означает, что намного проще вызвать асинхронный метод внутри Main
,
Итак RunAsync()
на IWebHost
можно вызвать внутри Main
вместо Run()
метод. Что-то вроде этого:
public static async Task Main(string[] args)
{
await BuildWebHost(args).RunAsync().ConfigureAwait(false);
}
Согласно документации, Run
метод:
Запускает веб-приложение и блокирует вызывающий поток до отключения хоста.
Тогда как RunAsync
метод:
Запускает веб-приложение и возвращает задание, которое завершается только при запуске токена или при завершении работы.
Мне было интересно, когда RunAsync
метод будет использоваться вместо обычного Run
метод? Каковы практические последствия этого? Заметит ли конечный пользователь какую-либо разницу?
2 ответа
Шаблоны ASP.NET Core по умолчанию содержат следующее Main
метод:
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
Тот Run
метод есть WebHostExtensions.Run
метод расширения, который реализован так:
public static void Run(this IWebHost host)
{
host.RunAsync().GetAwaiter().GetResult();
}
Так что это на самом деле называет WebHostExtensions.RunAsync
и просто блокирует его.
Теперь давайте посмотрим, как C# 7.1 асинхронный Main
указывается метод:
Когда один из [этих методов на основе задач] идентифицируется как точка входа, компилятор синтезирует фактический метод точки входа, который вызывает один из этих кодированных методов:
static Task Main()
приведет к компиляции, испускающей эквивалентprivate static void $GeneratedMain() => Main().GetAwaiter().GetResult();
static Task Main(string[])
приведет к компиляции, испускающей эквивалентprivate static void $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();
Так что в основном, имея асинхронный Main
метод как это:
public static async Task Main(string[] args)
{
await BuildWebHost(args).RunAsync();
}
Заставит компилятор также выдавать следующее:
private static void $GeneratedMain(string[] args)
{
Main(args).GetAwaiter().GetResult();
}
И если вы посмотрите внимательно на то, что происходит с возвращенной задачей, это почти то же самое, что и WebHostExtensions.Run
метод делает.
Так что это значит? Вы можете использовать любое из этих решений, и эффект будет одинаковым. Ваше приложение будет правильно блокироваться, пока асинхронная задача не будет решена. Нет практического различия между решениями. Единственное реальное преимущество, которое вы получили бы от использования асинхронного метода main, было бы, если бы у вас была другая асинхронная работа в Main
Способ; хотя это, вероятно, будет очень редким случаем, поскольку для веб-приложений вы, скорее всего, будете выполнять настройку в течение жизненного цикла приложения ASP.NET Core (т. е. в Startup
и не за его пределами).
Каковы практические последствия этого? Заметит ли конечный пользователь какую-либо разницу?
Нет никакой разницы в поведении уровня RunTime.
Поскольку эта функция не соответствует изменению кода CLR, асинхронный метод Main является всего лишь синтаксическим сахаром. Такая конструкция обеспечивает совместимость с предыдущими версиями языка. Чтобы узнать больше подробностей, см. Async Main в репо Roslyn Git.
- Серия C# 7, часть 2: Асинхронное соединение