我正在构建一个dotnet核心GenericHost应用程序,该应用程序启动动态数量的计划任务,该任务需要能够在数据库中更新每个任务时有选择地取消它们,但是我不确定采用哪种最佳方法
我已经建立了应用程序的基本框架,在进行了一些研究之后,我遇到了以下两种方法,我不确定哪种方法更有效/更能证明未来,并且我不确定确保遵循什么设计模式来跟踪预定任务及其相关的CancellationToken:
关于监视运行时间表及其相关的CancellationToken,我目前的想法是,我将这些信息存储在Dictionary中,其中时间表数据库ID为键,而CancellationToken为值。
方法1产生以下代码来排队新的后台工作项,并且似乎每个任务共享由QueuedHostedService设置的相同CancellationToken:
foreach (var schedule in schedules) {
// Enqueue a background work item
_taskQueue.QueueBackgroundWorkItem(async token => {
dict.Add(schedule.Id, token);
var guid = Guid.NewGuid().ToString();
for (var delayLoop = 0; delayLoop < 3; delayLoop++) {
_logger.LogInformation($"Queued Background Task {guid} is running. {delayLoop}/3");
await Task.Delay(TimeSpan.FromSeconds(5), token);
}
_logger.LogInformation($"Queued Background Task {guid} is complete. 3/3");
});
}
方法2产生以下代码,我强制每个启动的任务使用新的CancellationTokenSource:
foreach (var schedule in schedules) {
schedule.Increment();
var tokenSource = new CancellationTokenSource();
await taskFactory.StartNew(async () => {
try {
await schedule.Task.ExecuteAsync(tokenSource);
} catch (Exception ex) {
var args = new UnobservedTaskExceptionEventArgs(ex as AggregateException ?? new AggregateException(ex));
UnobservedTaskException?.Invoke(this, args);
if (!args.Observed) {
throw;
}
}
}, cancellationToken);
dict.Add(schedule.Id, tokenSource.Token);
}