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

时间:2016-01-07 18:22:19

标签: c# asp.net multithreading asp.net-web-api2

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

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

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

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

我想尽可能避免数据库/持久存储,并且我意识到在IIS工作进程中运行异步任务的风险 - 为了参数,后台处理是不重要。

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

1 个答案:

答案 0 :(得分:0)

您需要在所有可能的工作人员之间共享某种存储空间。例如,这可能是:

  • 静态变量。可能是最容易实现的,但是当应用程序不在一个AppDomain中运行时会有限制(如果你想扩展,这一点尤其重要)。所以可能不是最好的方式
  • SQL数据库:可能是最常见的一个。如果您的应用程序已经使用了一个,我会说要选择这条路线。
  • No-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*/;