gpt4 book ai didi

c# - 调度程序后台服务中的异步计时器

转载 作者:行者123 更新时间:2023-12-03 15:56:12 27 4
gpt4 key购买 nike

我正在 .Net-Core 中编写托管服务,该服务基于计时器在后台运行作业。

目前我必须像这样同步运行代码:

public override Task StartAsync(CancellationToken cancellationToken)
{
this._logger.LogInformation("Timed Background Service is starting.");

this._timer = new Timer(ExecuteTask, null, TimeSpan.Zero,
TimeSpan.FromSeconds(30));

return Task.CompletedTask;
}

private void ExecuteTask(object state)
{
this._logger.LogInformation("Timed Background Service is working.");
using (var scope = _serviceProvider.CreateScope())
{
var coinbaseService = scope.ServiceProvider.GetRequiredService<CoinbaseService>();
coinbaseService.FinalizeMeeting();
}
}

我想在计时器上运行此异步,但我不想使用火运行异步并忘记,因为它可能会导致我的代码中出现竞争条件。
例如(订阅 timer.Elapsed 事件)

有没有一种方法可以按定时计划利用异步代码,而无需执行即发即忘

最佳答案

async 的全部目的是不阻止主线程。但这已经是一个后台线程,所以它并不重要 - 除非它是一个 ASP.NET Core 应用程序。这是唯一重要的时间,因为线程池有限,耗尽意味着无法处理更多请求。

如果您真的想运行它 async ,只需将其设为 async :

private async void ExecuteTask(object state)
{
//await stuff here
}

是的,我知道你说你不想“开火后遗忘”,但事件真的就是这样:它们是开火后遗忘。因此,您的 ExecuteTask 方法将被调用,并且不会在意(或检查)它是 (1) 仍在运行还是 (2) 是否失败。 无论你是否运行这个 async 都是如此。

您可以通过将 ExecuteTask 方法的所有内容包装在 try/ catch 块中并确保将其记录在某处以便您知道发生了什么来减轻故障。

另一个问题是知道它是否仍在运行(即使您没有运行 async 也是一个问题)。还有一种方法可以缓解这种情况:
private Task doWorkTask;

private void ExecuteTask(object state)
{
doWorkTask = DoWork();
}

private async Task DoWork()
{
//await stuff here
}

在这种情况下,您的计时器只是启动任务。但不同之处在于您保留了对 Task 的引用。这将使您可以检查代码中其他任何位置的 Task 的状态。例如,如果要验证是否完成,可以查看 doWorkTask.IsCompleteddoWorkTask.Status

此外,当您的应用程序关闭时,您可以使用:
await doWorkTask;

在关闭应用程序之前确保任务已完成。否则,线程将被杀死,可能会使事情处于不一致的状态。请注意,如果 await doWorkTask 中发生未处理的异常,则使用 DoWork() 将引发异常。

在开始下一个任务之前验证上一个任务是否已完成也可能是一个好主意。

关于c# - 调度程序后台服务中的异步计时器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53844586/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com