I am developing a web application with a REST Api using C# with asp.net core 2.0
What I want to achieve is when the client send a request to an endpoint I will run a background task separated from the client request context which will be ended if the task started successfully.
I know there is HostedService but the problem is that the HostedService starts when the server starts, and as far as I know there is no way to start the HostedService manually from a controller.
Here is a simple code that demonstrate the question.
[Authorize(AuthenticationSchemes = "UsersScheme")]
public class UsersController : Controller
{
[HttpPost]
public async Task<JsonResult> StartJob([FromForm] string UserId, [FromServices] IBackgroundJobService backgroundService) {
//check user account
(bool isStarted, string data) result = backgroundService.Start();
return JsonResult(result);
}
}
Microsoft has documented the same at https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-2.1
It accomplishes using BackgroundTaskQueue, which gets work assigned from Controller and the work is performed by QueueHostedService which derives from BackgroundService.
You still can use
IHostedService
as base for background tasks in combination withBlockingCollection
.Create wrapper for
BlockingCollection
so you can inject it as singleton.Then in implementation of
IHostedService
"listen" for tasks and when tasks "arrive" execute it.BlockingCollection
will stop execution if collection is empty - so yourwhile
loop will not consume processor time..Take
method acceptcancellationToken
as argument. With token you can cancel "waiting" for next task when application stops.And in the controller you simply add task you want to run to our collection
Wrapper for blocking collection should be registered for dependency injection as singleton
Register background service