简体   繁体   中英

ASP.NET Core Return HTTP Response And Continue Background Worker With Same Context

Sorry ahead of time, this is a bit of a lengthy setup/question. I am currently working on an API using C# ASP.NET Core 2.1. I have a POST endpoint which takes about 5-10 seconds to execute (which is fine). I need to add functionality which could take a considerable amount of time to execute. My current load testing takes an additional 3 minutes. To be honest production could take a bit longer because I can't really get a good answer as to how many of these things we can expect to have to process. From an UX perspective, it is not acceptable to wait this long as the front end is waiting for the results of the existing POST request. In order to maintain an acceptable UX.

All services are set up as transient using the default ASP.NET Core DI container. This application is using EF Core and is set up in the same fashion as the services (sorry I am not at work right now and forgot the exact verbiage within the Setup file).

I first tried to just create a background worker, but after the response was sent to the client, internal objects would start to be disposed (ie entity db context) and it would eventualy throw errors when continuing to try executing code using said context (which makes sense since they were being disposed).

I was able to get a background worker mostly working by using the injected IServiceScopeFactory (default ASP.NET Core implementation). All my code executes successfully until I try saving to the DB. We have overridden the SaveChangesAsync() method so that it will automatically update the properties CreatedByName, CreatedTimestamp, UpdatedByName, and UpdatedTimestamp to the currently tracked entities respectively. Since this logic is used by an object created from the IServiceScopeFactory, it seems like it does not share the same HttpContext and therefore, does not update the CreatedByName and UpdatedByName correctly (tries to set these to null but the DB column does not accept null).

Right before I left work, I created a something that seemed to work, but it seems very dirty. Instead of using the IServiceScopeFactory within my background worker to create a new scope, I created an impersonated request using the WebClient object which pointed to an endpoint within the same API that was currently being executed. This did allow the response to be sent back to the client in a timely manor, and this did continue executing the new functionality on the server (updating my entities correctly).

I apologize, I am not currently at work and cannot provide code examples at this moment, but if it is required in order to fully answer this post, I will put some on later.

Ideally, I would like to be able to start my request, process the logic within the existing POST, send the response back to the client, and continue executing the new functionality using the same context (including the HttpContext which contains identity information). My question is, can this be done without creating an impersonated request? Can this be accomplished with a background worker using the same context as the original thread (I know that sounds a bit weird)? Is their another approach that I am completely missing? Thanks ahead of time.

查看Hangfire非常易于使用的库来执行后台任务。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM