如何防止创建处理同一请求的多个后台进程

本文关键字:后台进程 请求 何防止 创建 处理 | 更新日期: 2023-09-27 18:29:20

我有一个简单的WebApi控制器方法,其目的是触发一些后台处理并立即返回202接受的响应(而不必完成与202响应一致的后台处理)

public async Task<IHttpActionResult> DoSomething(string id)
{
    HostingEnvironment.QueueBackgroundWorkItem(async ct =>
    {
        //Do work
    }
    return ResponseMessage(new HttpResponseMessage(HttpStatusCode.Accepted));
}

然而,我希望能够防止对具有相同id的同一端点的多个请求同时触发同一后台处理的多个实例。

实际上,如果同时(或接近)发出两个具有相同id的请求,第一个请求将处理该id,第二个请求将能够识别该id并采取相应行动,而不会重复已经完成的工作。

如果可能的话,我希望避免使用数据库/持久存储,并且我知道在IIS工作进程中运行异步任务的风险——出于论证的目的,后台处理并不重要。

我该怎么做?任何帮助都将不胜感激。

如何防止创建处理同一请求的多个后台进程

您需要在所有可能的员工之间共享某种存储。例如:

  • 一个静态变量。可能是最容易实现的,但当应用程序不是只在一个AppDomain中运行时会有局限性(如果您想扩展,这一点尤为重要)。所以可能不是最好的方式
  • SQL数据库:可能是最常见的数据库。如果你的应用程序已经使用了一个,我会选择这条路线
  • 无SQL数据库,例如键值存储。如果您的应用程序还没有使用SQL数据库,则可能是一种替代方案
  • 一些外部组件,如工作流管理工具

编辑:使用ConcurrentDictionary的示例(根据线程启动器的请求-我仍然认为使用(可能是NoSQL)数据库将是最优雅的方式)-实际上,您可以将Tasks放入字典:

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*/;