.NET Core IHostedService 立即抛出 "A task was canceled"
.NET Core IHostedService throws "A task was canceled" immediately
我正在尝试在每小时运行一次的 .NET Core 3.1 应用程序中构建一项服务。我的服务每小时运行一次(即在 StartAsync()
中遇到断点),但实施立即抛出以下错误:
A task was canceled
我搜索了很多,但我很难找到有用的回复;似乎这些是在使用 HttpClient
时最常抛出的,这与我的情况无关。
就是说,我有一种预感,我应该等待 某事 ,但我尝试添加 await
导致应用程序在启动时挂起(我想我无意中等待了完整的每小时迭代......?)。 tutorial I've been following 不会在任何地方使用 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();
}
如果您想在宿主程序启动和停止时 运行 编码,IHostedServce
非常有用。您定义的每个服务将按照您定义的顺序启动和停止。但是如果您的启动方法永远不会完成,主机应用程序将永远不会启动。
如果您想要的只是一个长 运行ning 循环,BackgroundService
会为您处理启动/停止生命周期。
public class MyService : BackgroundService{
protected override async Task ExecuteAsync(CancellationToken stoppingToken){
while(!stoppingToken.IsCancellationRequested){
await Task.Delay(...., stoppingToken);
//
}
}
}
请注意,如果您从来没有 await
未完成的任务,您的服务仍然可以阻止主机的启动。
我正在尝试在每小时运行一次的 .NET Core 3.1 应用程序中构建一项服务。我的服务每小时运行一次(即在 StartAsync()
中遇到断点),但实施立即抛出以下错误:
A task was canceled
我搜索了很多,但我很难找到有用的回复;似乎这些是在使用 HttpClient
时最常抛出的,这与我的情况无关。
就是说,我有一种预感,我应该等待 某事 ,但我尝试添加 await
导致应用程序在启动时挂起(我想我无意中等待了完整的每小时迭代......?)。 tutorial I've been following 不会在任何地方使用 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();
}
IHostedServce
非常有用。您定义的每个服务将按照您定义的顺序启动和停止。但是如果您的启动方法永远不会完成,主机应用程序将永远不会启动。
如果您想要的只是一个长 运行ning 循环,BackgroundService
会为您处理启动/停止生命周期。
public class MyService : BackgroundService{
protected override async Task ExecuteAsync(CancellationToken stoppingToken){
while(!stoppingToken.IsCancellationRequested){
await Task.Delay(...., stoppingToken);
//
}
}
}
请注意,如果您从来没有 await
未完成的任务,您的服务仍然可以阻止主机的启动。