我几乎使用 Microsoft 文档中提供的示例来排队后台任务。
在这个队列中,我添加了一个Func<Task>
, 稍后由QueuedHostedService
.
控制器 - HTTP POST
...
Func<Task> workItem = () => _mockService.DoWorkAsync(guid);
_queue.QueueBackgroundWorkItem(workItem);
return Ok();
模拟服务.DoWorkAsync
var data = await _insideMockService.GetAsync();
await _anotherService.Notify(data);
BackgroundTaskQueue.QueueBackgroundWorkItem
private ConcurrentQueue<Func<Task>> _workItems
private SemaphoreSlim _signal = new SemaphoreSlim(0);
public void QueueBackgroundWorkItem(Func<Task> workItem)
{
if (workItem == null)
{
throw new ArgumentNullException(nameof(workItem));
}
_workItems.Enqueue(workItem);
_signal.Release();
}
QueuedHostedService.ExecuteAsync
_currentTask = await _queue.DequeueAsync(cancellationToken);
try
{
await _currentTask();
...
BackgroundTaskQueue.DequeueAsync
public async Task<Func<Task>> DequeueAsync(CancellationToken cancellationToken)
{
await _signal.WaitAsync(cancellationToken);
_workItemsById.TryDequeue(out var workItem);
return workItem;
}
启动.ConfigureServices
services.AddScoped<IMockService, MockService>(); // Implements DoWorkAsync
services.AddScoped<IInsideMockService, InsideMockService>(); // DoWorkAsync requires this dependency
services.AddScoped<IAnotherService, AnotherService>(); // DoWorkAsync requires this dependency
services.AddHostedService<QueuedHostedService>();
services.AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>();
IMockService.DoWorkAsync
方法使用scoped
服务。将此方法的引用添加到驻留在singleton
服务中的队列中。该队列稍后由HostedService
也是 a的 a 读取singleton
。
是否有可能在DoWorkAsync
处理之前处理服务引用HostedService
?如果我们排除应用程序正常(或不正常)关闭的场景。
一些可能有一百个请求的本地测试运行(以及一些添加Task.Delay
的请求DoWorkAsync
)似乎工作正常,但我不确定我是否遗漏了什么..