Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Long running task in ApiController (using WebAPI, self-hosted OWIN)

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.

like image 880
Deniz Avatar asked Aug 12 '16 11:08

Deniz


People also ask

Can Web API be self hosted?

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.

What is OWIN used for in Web API?

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.

When running a self hosted server might need administrative privileges on the machine select Yes or no?

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.


2 Answers

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.

like image 186
Oliver Hanappi Avatar answered Oct 05 '22 21:10

Oliver Hanappi


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!"));
like image 41
SFun28 Avatar answered Oct 05 '22 20:10

SFun28