我正在开发一个API,我的端点接受一个ID,然后执行繁重的操作来编写结果(生成PDF)。
我可能会在短时间内多次获得相同资源的相同请求,因此我想要某种跟踪ID的工作队列,第一个请求会启动实际工作并且以下请求将(首先检查它是否已经在管道中)然后等待工作完成并返回相同的结果。
首先我想也许ConcurrentDictionary
会有用,但我不知道如何处理等待工作完成部分。我也看了ObservableCollection
,但我不确定它的安全性(没有花太多精力手动安全)。
答案 0 :(得分:2)
如果您希望能够扩展它,我会建议使用消息队列的替代架构(例如RabbitMQ)。您的API只会将消息发布到队列中,然后您可以使用Windows服务来使用消息并处理它们。这两个应用程序当然可以共享一个公共数据存储,以便同步信息。
答案 1 :(得分:0)
我可能会使用一个普通的字典,其中有一个锁定和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);
}
});