c# - 异步运行多个任务并在任务完成时将新任务添加到任务列表中
问题描述
抱歉标题不好,我不知道如何简洁地描述这一点。
我正在.net core 中构建一个服务来处理文件。一般的想法是(在循环中)通过使用 DB 调用检查要在文件上运行的新任务,如果找到,则将它们异步触发。会有一个限制器来限制正在运行的任务的数量。如果它达到限制,它会等到一个任务完成后再启动一个新的。如果 DB 调用没有返回任何内容,那么它只会休眠一会儿,然后再试一次。
我认为相当基本,但我遇到了问题,因为我读过的所有内容都说您应该始终等待任务,而不是“开火就忘记”。但如果我这样做,那么我要么同步运行文件,要么批量处理它们。我错过了一些我确定的东西。
目前它被实现为 IHostedService(特别是BackgroundService)。这是我们完成工作的主要 ExecuteAsync 方法。实施为“一劳永逸”。(Visual Studio 在 Task.Run 上给出“呼叫未等待”警告)
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
var throttleTimeout = 10000;
//set up semaphore
var taskThrottler = new SemaphoreSlim(10, 10);
while (!stoppingToken.IsCancellationRequested)
{
//wait for free slot
await taskThrottler.WaitAsync(throttleTimeout,stoppingToken);
//get next file to process
var currentFile = await _fileService.GetNextFileForProcessing();
// create task
Task.Run( async
() =>
{
try
{
//do work with file tracker
var result = await _fileProcessorController.ProcessFile(currentFile);
}
finally
{
taskThrottler.Release();
}
}
, stoppingToken);
}
}
现在,如果我更改它并在 Task.Run 之前添加等待,那么我(本质上)将同步运行,因为每个任务将在下一个任务被触发之前被等待..
如果我将任务添加到列表中,我可以使用“await Task.WhenAll(tasks);”。但后来我在批处理。
我需要能够优雅地处理失败的处理作业,所以我认为必须以某种形式等待。
我发现的所有解决类似问题的示例通常都有提前完成的任务(或文件)列表,然后迭代。但是当我需要在处理其他任务时将任务添加到列表中时,我不确定最好的方法是什么。
也许使用任务列表和WhenAny的东西?然后如果找到任何新任务,我可以在每个循环的任务列表中添加新任务吗?
解决方案
推荐阅读
- typescript - Typescript 条件对象键:Prop A 存在 Prob B 必须存在
- html - 溢出:滚动导致容器隐藏溢出。有什么办法吗?
- node.js - Mongoose - 我将如何限制推送数组的大小?
- javascript - 实现 React 组件时,DevTools Failed to Sourcemap 错误
- javascript - 如何在反应中正确显示从 api 获取的数据?
- c - 如果我用 fread 读取图片并立即将所有读取的数据写入文件,则原始文件(图片)与新写入的文件完全不同
- amazon-web-services - 如何在 Sagemaker .py 训练中绘制训练指标的历史记录
- javascript - 如何从表格中的单元格中获取值?
- c# - 如何实现从 Solids 中去除材料?(如 CAM 模拟)
- kubernetes - Kubernetes pod - 何时准备好为流量提供服务?