asp.net - Starting and Forgetting an Async task in MVC Action -
i have standard, non-async action like:
[httppost] public jsonresult startgeneratepdf(int id) { pdfgenerator.current.generateasync(id); return json(null); }
the idea being know pdf generation take long time, start task , return, not caring result of async operation.
in default asp.net mvc 4 app gives me nice exception:
system.invalidoperationexception: asynchronous operation cannot started @ time. asynchronous operations may started within asynchronous handler or module or during events in page lifecycle. if exception occurred while executing page, ensure page marked <%@ page async="true" %>.
which kinds of irrelevant scenario. looking can set flag false prevent exception:
<appsettings> <!-- allows throwaway async operations mvc controller actions --> <add key="aspnet:allowasyncduringsyncstages" value="true" /> </appsettings>
https://stackoverflow.com/a/15230973/176877
http://msdn.microsoft.com/en-us/library/hh975440.aspx
but question is, there harm kicking off async operation , forgetting synchronous mvc controller action? can find recommends making controller async, isn't i'm looking - there no point since should return immediately.
relax, microsoft says (http://msdn.microsoft.com/en-us/library/system.web.httpcontext.allowasyncduringsyncstages.aspx):
this behavior meant safety net let know on if you're writing async code doesn't fit expected patterns , might have negative side effects.
just remember few simple rules:
never await inside (async or not) void events (as return immediately). webforms page events support simple awaits inside them -
registerasynctask
still highly preferred approach.don't await on async void methods (as return immediately).
don't wait synchronously in gui or request thread (
.wait()
,.result()
,.waitall()
,waitany()
) on async methods don't have.configureawait(false)
on root await inside them, or roottask
not started.run()
, or don't havetaskscheduler.default
explicitly specified (as gui or request deadlock).use
.configureawait(false)
ortask.run
or explicitly specifytaskscheduler.default
every background process, , in every library method, not need continue on synchronization context - think of "calling thread", know not 1 (and not on same one), , may not exist anymore (if request ended). alone avoids common async/await errors, , increases performance well.
microsoft assumed forgot wait on task...
update: stephen (pun not intended) stated in answer, there inherit hidden danger forms of fire-and-forget when working application pools, not solely specific async/await, tasks, threadpool, , other such methods - not guaranteed finish once request ends (app pool may recycle @ time number of reasons).
you may care or not (if it's not business-critical in op's particular case), should aware of it.
Comments
Post a Comment