Подтвердить что ты не робот

Как обрабатывать операции async в Startup.Configure?

В моем приложении ASP.NET 5 я хочу загрузить некоторые данные из Azure в кеш внутри моего метода Startup.Configure. Azure SDK предоставляет только асинхронные методы. Как правило, вызов метода async выполняется через ожидание внутри асинхронного метода, например:

public async Task Configure(IApplicationBuilder app, IMemoryCache cache)
{
    Data dataToCache = await DataSource.LoadDataAsync();
    cache.Set("somekey", dataToCache);

    // remainder of Configure method omitted for clarity
}

Однако ASP.NET 5 требует, чтобы метод Configure возвращал void. Я мог бы использовать метод async void, но я понимаю, что методы async void должны использоваться только для обработчиков событий (согласно https://msdn.microsoft.com/en-us/magazine/jj991977.aspx среди многих других).

Я думал, что лучший способ сделать это - это вызвать функцию async без ожидания, вызвать Wait из возвращенной задачи, а затем кешировать результаты с помощью свойства Task.Results, например:

public void Configure(IApplicationBuilder app, IMemoryCache cache)
{
    Task<Data> loadDataTask = DataSource.LoadDataAsync();
    loadDataTask.Wait();
    cache.Set("somekey", loadDataTask.Result);

    // remainder of Configure method omitted for clarity
}

Стивен Вальтер использовал аналогичный подход в сообщении в начале этого года. Однако это неясно из этой должности, если это считается приемлемой практикой. Это?

Если это считается приемлемой практикой, что - если есть - обработка ошибок мне нужна? Мое понимание заключается в том, что Task.Wait() будет перебрасывать любые исключения, вызванные операцией async, и я не предоставил никакого механизма для отмены операции async. Просто вызывается Task.Wait() достаточно?

4b9b3361

Ответ 1

В примере кода в блоге, с которым вы связались, использовался только sync-over-async, чтобы заполнить базу данных примерами данных; этот вызов не будет существовать в производственном приложении.

Во-первых, я бы сказал, что если вам действительно нужно Configure быть асинхронным, тогда вы должны поднять проблему с командой ASP.NET, чтобы она была на их радаре. Было бы не слишком сложно для них добавить поддержку ConfigureAsync в этот момент (то есть до выпуска).

Во-вторых, у вас есть несколько подходов к проблеме. Вы можете использовать task.Wait (или, еще лучше, task.GetAwaiter().GetResult(), что позволяет избежать обертки AggregateException, если ошибка возникает). Или вы можете кэшировать задачу, а не результат задачи (которая работает, если IMemoryCache - это скорее словарь, чем какая-то странная операция сериализации в двоичном массиве в памяти - я смотрю на вас, предыдущий версии ASP.NET).

Если это считается приемлемой практикой, что - если есть - обработка ошибок мне нужна?

Использование GetAwaiter().GetResult() приведет к тому, что исключение (если оно есть) распространится из Configure. Я не уверен, как ответ ASP.NET будет, если конфигурация приложения не удалась.

Я не предоставил никакого механизма для отмены операции async.

Я не уверен, как вы можете "отменить" настройку приложения, поэтому я не стал бы беспокоиться об этой части.

Ответ 2

Вы можете выполнить некоторую асинхронную работу, но этот метод является синхронным, и вы не можете его изменить. Это означает, что вам нужно синхронно ждать завершения асинхронных вызовов.

Вы не хотите возвращаться из метода Startup, если запуск еще не закончен, правильно? Ваше решение кажется все в порядке.

Что касается обработки исключений: если часть работы, с которой ваше приложение не может работать нормально, вы должны позволить сбой метода Startup (см. Fail-fast). Если это не что-то важное, я бы включил соответствующую часть в блок catch try и просто зарегистрировал проблему для последующего контроля.