Disclaimer : I may have a bad idea !
I have a middleware on ASP.NET 5.
This middleware process the request and start a new Task
. The task is mainly for statistics purposes.
The middleware do not care of the result of this task.
For performances reason, I would like to continue the ASP.NET pipeline without awaiting for the "background" task.
I see three way to implement this :
1/ Start the task, no await
or .Wait()
. Do no care about unobserved exception.
2/ Register the task within an "observer
". The observer will observer all the tasks until the application ends.
3/ Use a service bus and/or a kind of worker role / WebJob.
I do not like the solution 1/.
The solution 3/ seems excessive.
The solution 2/ is OK to me, with something like that :
public class TaskObserver : IDisposable
{
private readonly List<Task> _tasks = new List<Task>();
public void RegisterTask(Task task)
{
_tasks.Add(task)
}
public void Dispose()
{
Task.WaitAll(_tasks.ToArray());
}
}
// somewhere in the service configuration...
serviceCollection.AddSingleton<TaskObserver>();
The Observer will be disposed at the end application by its container.
I could even add a Timer
for cleaning completed tasks at regular interval.
Is the 2/ solution correct in an ASP.NET 5 context ?
The bottom line is that ASP.NET was not designed for doing work that is not an HTTP request. There's a few different ways to try to hack together a fire-and-forget situation (as I describe on my blog), but none of them are foolproof.
WebJobs, on the other hand, are designed for exactly this scenario. So the best answer is "just use WebJobs". Give them a try; they're probably not as hard as you think.
However, if you really want to take the less-reliable route of doing background work in the ASP.NET AppDomain, then there are varying degrees of hacks to try. E.g., if you're willing to take a dependency on the full .NET framework (not just core), then you can use
HostingEnvironment.QueueBackgroundWorkItem
.