How do I prevent the creation of multiple background processes working on the same request?

China☆狼群 提交于 2020-01-04 06:58:44

问题


I have a simple WebApi controller method that's purpose is to trigger some background processing and return a 202 Accepted response immediately (without necessarily having completed the background processing as is consistent with a 202 response.)

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

However, I want to be able to prevent multiple requests to the same endpoint with the same id from triggering multiple instances of the same background processing simultaneously.

Effectively, if two requests with the same id's were to be made at the same time (or near enough), the first one would do the processing for that id and the second one would be able to identify this and take action accordingly and not duplicate the work that's already being done.

I'd like to avoid databases/persistent storage if at all possible and I'm aware of the risks of running async tasks within an IIS worker process - for the sake of the argument, the background processing is not critical.

How can I go about doing this? Any help would be much appreciated.


回答1:


You'll need some kind of storage shared between all your possible workers. This could be, for example:

  • A static variable. Probably the easiest to implement, but has limitations when the application does not run in only one AppDomain (especially important if you want to scale). So probably not the best way
  • An SQL Database: Probably the most common one. If your application already uses one, I'd say go for this route.
  • A No-SQL database, for example a key-value store. Might be an alternative if your application does not use a SQL database yet.
  • Some external component such a workflow management tool

EDIT: Example using ConcurrentDictionary (per request of the thread starter - I stil think using a (possibly NoSQL) database would be the most elegant way) - actually you could just put Tasks into the dictionary:

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


来源:https://stackoverflow.com/questions/34662403/how-do-i-prevent-the-creation-of-multiple-background-processes-working-on-the-sa

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!