我正在开发一个API,其中我的端点接受ID,然后执行繁重的操作来合成结果(生成PDF)。
我可能会在很短的时间内多次收到相同资源的相同请求,所以我想要某种跟踪ID的工作队列,第一个请求将启动实际的工作,随后的请求将(首先检查它是否已经在管道中,然后)只需等到工作完成并返回相同的结果即可。
首先,我认为aConcurrentDictionary
可能会有用,但是我不知道如何处理直到完成工作为止的等待。我也查看了ObservableCollection
,但是我不确定它的安全性(没有花费过多的精力来手动使其安全)。
我可能会使用一个普通的字典,该字典的周围和Task
内部都带有锁,当计算出工作项的结果时,这些字典就完成了。
这意味着将工作的每个部分都表示为Task<WorkResult>
。
如果收到新请求,您可以执行以下操作:
lock (currentWork)
{
Task<WorkResult> workItem = null;
if (currentWork.TryGetResult(workId, out workItem))
{
// Work is already in progress. Reuse that work item
return workItem; // The caller can await that
}
// Create a new workItem
workItem = FunctionThatStartsWork(); // Could also be a Task.Run(...) thing
// Store it in the map
currentWork[workId] = workItem;
// Return it to the caller so that he can await it
return workItem;
}
现在还有一个问题是谁从字典中删除该项目。一种方法可能是继续创建工作任务,一旦完成,该任务就会从地图中删除。
workItem.ContinueWith(wi => {
lock (currentWork) {
currentWork.Remove(workId);
}
});
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句