Chciałbym uruchomić długo działające zadanie (np. 4-5 minut) w ApiControllerze w środowisku hostowanym samodzielnie OWIN. Jednak chciałbym wysłać odpowiedź z powrotem po uruchomieniu tego zadania (jak tylko uruchomiłem zadanie długotrwałe) bez czekania, aż to się skończy. To długo działające zadanie nie ma nic wspólnego z HTTP i sekwencyjnie uruchamia niektóre metody, które mogą zająć bardzo dużo czasu.Długie uruchamianie zadania w ApiControllerze (przy użyciu WebAPI, selfhosted OWIN)
Przeczytałem na blogu this i postanowiłem spróbować pod numerem QueueBackgroundWorkItem
. Jednak nie jestem pewien, czy możliwe jest użycie tej metody w środowisku hostowanym samodzielnie (aplikacja konsolowa) lub konieczne do korzystania z tej metody. W samodzielnej aplikacji konsolowej myślę, że sama aplikacja zarządza żądaniami i wszystkie żądania działają w tym samym AppDomain (aplikacje domyślnie AppDomain, nie tworzymy żadnych nowych appDomain), więc mogę po prostu uruchomić długo działające zadanie moda na ogień i zapomnienie, bez robienia czegoś wyjątkowego?
W każdym razie, kiedy używam QueueBackgroundWorkItem
, zawsze pojawia się błąd:
<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>
Również znalazłem this pytanie na SO i szczerze mówiąc wydaje się trochę mylące dla mnie, jako jedynej drogi do osiągnięcia tego to jest IRegisteredObject
czy nie?
Po prostu próbuję uruchomić długo działające zadanie w aplikacji hostowanej samodzielnie i doceniam wszelkie pomysły na ten temat. Niemal wszystkie zasoby, pytania, które znalazłem, są oparte na asp .net i nie jestem pewien, od czego zacząć.
Czy to nie jest opcja, aby umieścić w kolejce zadanie (w bazie danych) i pozwolić, aby jakaś usługa go obsłużyła? –
Hangfire (https://www.hangfire.io/) robi coś podobnego, o ile wiem.Uważam jednak, że to trochę inaczej niż pytanie. – Deniz