I would like to run a long running task (say 4-5 minutes) in an ApiController within a self-hosted OWIN environment. However I would like to send a response back after starting that task (as soon as I started the long running task) without waiting it to finish. This long running task has nothing to do with the HTTP and sequentially runs some methods which may take very long.
I have a look at this blog post and decided to give a try to QueueBackgroundWorkItem
. However, I am not sure if it is possible to use this method in a self-hosted (console application) owin environment or necessary to use it. In a self-hosted console application I think, the application itself manage the requests and all request run within the same AppDomain (applications default AppDomain, we do not create any new appDomain), so may be I can just run a long running task in a fire-and-forget fashion, without doing anything special?
Anyway, when I use QueueBackgroundWorkItem
, I always get the error:
<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>
Operation is not valid due to the current state of the object.
</ExceptionMessage>
<ExceptionType>System.InvalidOperationException</ExceptionType>
<StackTrace>
at System.Web.Hosting.HostingEnvironment.QueueBackgroundWorkItem(Func`2 workItem) at BenchMarkService.SmokeTestController.IsItWorking() in C:\Devel\Code\Projects\BenchMarkService\BenchMarkService\SmokeTestController.cs:line 18 at lambda_method(Closure , Object , Object[] ) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()
</StackTrace>
</Error>
Also I found this question on SO and to be honest it seems a little bit confusing to me as the only way to achieve that is IRegisteredObject
or not?
I am just trying to run a long running task in a self-hosted application and I appreciate any ideas about that. Almost all of the resources, questions I found are based on asp .net and I am not sure where to start.
ASP.NET Web API does not require IIS. You can self-host a web API in your own host process. New applications should use OWIN to self-host Web API. See Use OWIN to Self-Host ASP.NET Web API 2.
Open Web Interface for . NET (OWIN) defines an abstraction between . NET web servers and web applications. OWIN decouples the web application from the server, which makes OWIN ideal for self-hosting a web application in your own process, outside of IIS.
Well, you do not need administrative privileges to start it. You only need them if you do not have the right to use the URL. ACLURL (tool) can be used in the installer to grant the right to a user or program. Then there will be no administrative privileges required at runtime.
Self-hosted OWIN applications are typically regular console applications, therefore you can spin off some long running task in the same way you would do that in a console application, e.g.:
Task.Run
ThreadPool.QueueUserWorkItem
new Thread(...).Start()
In IIS hosted ASP.NET applications it is not advisable to use such methods because application pools are commonly recycled, hence your application gets shut down and restarted pretty often. In such a case your background task would be aborted. In order to prevent (or postpone) that, APIs like QueueBackgroundWorkItem
have been introduced.
However because you are self-hosted and do not run in IIS, you can just use the APIs listed above.
This is pretty much what Hangfire was created to do (https://www.hangfire.io/).
Sounds like a fire-and-forget job.
var jobId = BackgroundJob.Enqueue(
() => Console.WriteLine("Fire-and-forget!"));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With