Я пытаюсь встроить службу в свое приложение .NET Core 3.1, которое работает ежечасно. Моя служба запускается каждый час (т. е. достигает точки останова в StartAsync()
), но реализация немедленно выдает следующую ошибку:
Задача была отменена
Я искал довольно много, однако мне трудно найти полезные ответы; кажется, что они чаще всего возникают при использовании HttpClient
, что не имеет отношения к моему случаю.
Тем не менее, у меня есть подозрение, что я должен ожидать чего-то, но мои попытки добавить await
привели к зависанию приложения при запуске (я полагаю, что непреднамеренно ждал полной часовой итерации...?) . В учебнике, которому я следовал, нигде не используйте await
; за исключением недосмотра (очень возможно), мой код кажется идентичным показанному примеру.
Я вытащил кишки ExecuteAll()
, чтобы подтвердить код в работах.
Спасибо.
public Task StartAsync(CancellationToken cancellationToken)
{
TimeSpan interval = TimeSpan.FromHours(1);
var nextRunTime = DateTime.Today.AddHours(DateTime.UtcNow.Hour + 1);
var curTime = DateTime.UtcNow;
var firstInterval = nextRunTime.Subtract(curTime);
//Run once on startup
TriggerHourlyService(null);
void action()
{
//Schedule the first iteration
var t1 = Task.Delay(firstInterval);
t1.Wait();
TriggerHourlyService(null);
//Schedule hourly
_timer = new Timer(
TriggerHourlyService,
null,
TimeSpan.Zero,
interval
);
}
Task.Run(action);
return Task.CompletedTask;
}
private void TriggerHourlyService(object state)
{
using var scope = _serviceScopeFactory.CreateScope();
IHourlyService hourlyService = scope.ServiceProvider.GetRequiredService<IHourlyService>();
//ASYNC METHOD
hourlyService.ExecuteAll();
}
Обновлять
После некоторых заметок из комментариев я немного переписал код, чтобы отойти от учебника (похоже, он продвигал некоторые опасные методы). Однако с этим переписыванием мое приложение зависает при запуске. Я считаю, что проблема связана с await Task.Delay(...)
, но у меня сложилось впечатление, что это не блокирует.
public async Task StartAsync(CancellationToken cancellationToken)
{
TimeSpan interval = TimeSpan.FromHours(1);
var nextRunTime = DateTime.UtcNow.Date.AddHours(DateTime.UtcNow.Hour + 1);
var curTime = DateTime.UtcNow;
var firstInterval = nextRunTime.Subtract(curTime);
//Run once on startup
await TriggerHourlyService(null);
//First run on next hour
await Task.Delay(firstInterval);
await TriggerHourlyService(null);
//Schedule hourly
_timer = new Timer(
async (state) => await TriggerHourlyService(state),
null,
TimeSpan.Zero,
interval
);
}
private async Task TriggerHourlyService(object state)
{
using var scope = _serviceScopeFactory.CreateScope();
IHourlyService hourlyService = scope.ServiceProvider.GetRequiredService<IHourlyService>();
await hourlyService.ExecuteAll();
}
IHostedService
— это стандартная зависимость с ограниченной областью действия в .NET Core. Он запускается при запуске приложения до того, как будет настроен конвейер обработки запросов приложения, отсюда и мое замешательство. Кроме того, чтобы уточнить, когда я сказалHttpClient
, я имел в виду классHttpClient
- эта задача была отменена, исключение кажется общим с тайм-аутами. Я ценю вашу помощь! - person Santi   schedule 27.04.2021hourlyService.ExecuteAll();
не блокирует, то ваш поставщик услуг и все, что им создано, удаляется до того, как что-либо внутри этого метода будет запущено. Кроме того, ваш код может зайти в тупик, вызвав:t1.Wait();
. Вы должны перестроить эту часть, чтобы вы могли должным образомawait
ее. - person Silvermind   schedule 27.04.2021IHostedService
вводится как переходный. - person Andy   schedule 27.04.2021IHostedService
. - person Santi   schedule 27.04.2021Task.Delay
реализуетTimer
из того, что я читаю), чтобы настроить его на час. Но теперь приложение зависает при запуске. - person Santi   schedule 27.04.2021BackgroundService
. - person Jeremy Lakeman   schedule 27.04.2021Task.Run
или.Wait()
. Все ожидается и т.д. Единственное, что не отражено в моем обновлении, это изменение сIHostedService
наBackgroundService
, которое я с тех пор сделал. - person Santi   schedule 27.04.2021