我有一个简单的 WebApi Controller 方法,其目的是触发一些后台处理并立即返回 202 已接受响应(不必完成与 202 响应一致的后台处理。)
public async Task<IHttpActionResult> DoSomething(string id)
{
HostingEnvironment.QueueBackgroundWorkItem(async ct =>
{
//Do work
}
return ResponseMessage(new HttpResponseMessage(HttpStatusCode.Accepted));
}
但是,我希望能够防止对具有相同 ID 的同一端点的多个请求同时触发同一后台处理的多个实例。
实际上,如果同时(或足够接近)发出具有相同 ID 的两个请求,第一个请求将处理该 ID,第二个将能够识别并采取相应的行动而不是重复已经完成的工作。
如果可能的话,我想避免使用数据库/持久存储,并且我知道在 IIS 工作进程中运行异步任务的风险——为了论证,后台处理并不重要。
我该怎么做呢?任何帮助将不胜感激。
最佳答案
您需要在所有可能的工作人员之间共享某种存储空间。这可能是,例如:
- 静态变量。可能是最容易实现的,但当应用程序不只在一个 AppDomain 中运行时会有限制(如果你想扩展,这一点尤其重要)。所以可能不是最好的方法
- 一个 SQL 数据库:可能是最常见的一个。如果您的应用程序已经使用了一个,我会说走这条路。
- No-SQL 数据库,例如键值存储。如果您的应用程序尚未使用 SQL 数据库,则可能是替代方案。
- 一些外部组件,例如工作流管理工具
编辑: 使用 ConcurrentDictionary 的示例(根据线程启动器的请求 - 我仍然认为使用(可能是 NoSQL)数据库将是最优雅的方式) - 实际上你可以将任务放入字典中:
private ConcurrentDictionary<string, Task<SomeType>> _cache = new //...
var task = _cache.GetOrAdd("<Key>", key => Task.Run(() => /*do some work*/));
if (task.IsCompleted)
/*result ready*/;
else
/*have to wait*/;
关于c# - 如何防止创建处理同一请求的多个后台进程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34662403/