Chr*_*ini 7 asp.net asynchronous invalidoperationexception synchronous controller-action
我有一个标准的,非异步的动作,如:
[HttpPost]
public JsonResult StartGeneratePdf(int id)
{
PdfGenerator.Current.GenerateAsync(id);
return Json(null);
}
Run Code Online (Sandbox Code Playgroud)
这个想法是我知道这个PDF生成可能需要很长时间,所以我只是启动任务并返回,而不是关心异步操作的结果.
在默认的ASP.Net MVC 4应用程序中,这给了我这个很好的例外:
System.InvalidOperationException:此时无法启动异步操作.异步操作只能在异步处理程序或模块中启动,或者在页面生命周期中的某些事件中启动.如果在执行页面时发生此异常,请确保将页面标记为<%@ Page Async ="true"%>.
哪种与我的场景无关.调查它我可以将标志设置为false以防止此异常:
<appSettings>
<!-- Allows throwaway async operations from MVC Controller actions -->
<add key="aspnet:AllowAsyncDuringSyncStages" value="true" />
</appSettings>
Run Code Online (Sandbox Code Playgroud)
/sf/answers/1066168141/
http://msdn.microsoft.com/en-us/library/hh975440.aspx
但问题是,通过启动这个异步操作并从同步MVC控制器动作中忘记它有什么危害吗?我能找到的一切都建议让控制器异步,但这不是我想要的 - 没有意义,因为它应该总是立即返回.
正如微软自己所说的那样放松(http://msdn.microsoft.com/en-us/library/system.web.httpcontext.allowasyncduringsyncstages.aspx):
如果您正在编写不符合预期模式且可能具有负面影响的异步代码,则此行为意味着您可以尽早了解安全网.
记住一些简单的规则:
永远不要等待内部(异步或非异常)void事件(因为它们立即返回).一些WebForms Page事件支持其中的简单等待 - 但RegisterAsyncTask仍然是首选的方法.
不要等待异步void方法(因为它们立即返回).
不要同步等待在GUI或请求线程(.Wait(),.Result(),.WaitAll(),WaitAny()在异步方法)不具有.ConfigureAwait(false)对根里面等待着他们,或他们根本Task不与启动.Run(),或没有TaskScheduler.Default明确规定(如GUI或请求将因此陷入僵局).
使用.ConfigureAwait(false)或Task.Run或明确指定TaskScheduler.Default为每一个后台进程,并在每个库的方法,但这并不需要继续在同步上下文-把它作为"调用线程",但要知道,这不是一个(而不是始终在同一个),甚至可能不再存在(如果请求已经结束).仅此一项就可以避免最常见的异步/等待错误,并且还可以提高性能.
微软只是假设你忘了等待你的任务......
更新:正如斯蒂芬清楚地(他并不打算)在他的回答中所说的那样,在使用应用程序池时,存在一种继承但隐藏的危险,包括所有形式的即发即弃,而不仅仅是async/await,而是Tasks,ThreadPool ,以及所有其他此类方法 - 一旦请求结束,它们不能保证完成(应用程序池可能由于多种原因随时回收).
您可能会关心与否(如果OP在特定情况下不是关键业务),但您应该始终了解它.
| 归档时间: |
|
| 查看次数: |
5025 次 |
| 最近记录: |