Microsoft做出了避免在引入
asyncASP.NET
时尽可能避免向后兼容性问题的决定。他们希望将其引入所有“一个ASP.NET”中-因此
async支持WinForms,MVC,WebAPI,SignalR等。
从历史上看,ASP.NET从.NET
2.0开始就通过基于事件的异步模式(EAP)支持干净的异步 *** 作,其中异步组件将
SynchronizationContext其开始和完成通知给。.NET
4.5对该支持进行了第一个相当大的更改,更新了核心ASP.NET异步类型以更好地启用基于任务的异步模式(TAP,即
async)。
同时,每个不同的框架(WebForm,MVC等)都开发了自己的与该内核进行交互的方式,将 向后兼容性
作为优先事项。为了帮助开发人员,
SynchronizationContext除了您看到的异常之外,还增强了核心ASP.NET 。它将捕获许多使用错误。
在WebForms世界中,他们有,
RegisterAsyncTask但是很多人只使用
async void事件处理程序。因此,ASP.NET
SynchronizationContext将
async void在页面生命周期的适当时间允许访问,如果在不适当的时间使用它,则会引发该异常。
在MVC / WebAPI / SignalR世界中,框架被结构化为服务。因此,他们能够以
asyncTask非常自然的方式采用,并且该框架只需要处理返回的内容
Task-一个非常干净的抽象。附带说明,您不再需要
AsyncController了。MVC知道它是异步的,因为它返回
Task。
但是,如果您尝试返回a
Task并 使用
asyncvoid,则不支持。而且没有什么理由支持它。仅支持不应该这样做的用户将是非常复杂的。请记住,它
asyncvoid会
SynchronizationContext直接绕过MVC框架直接通知核心ASP.NET
。MVC框架了解如何等待您,
Task但它甚至不了解
async void,因此它将完成返回到ASP.NET核心,该核心看到它 实际上 尚未完成。
在两种情况下,这可能会导致问题:
- 您正在尝试使用某些库或使用的库
async void
。抱歉,但是明显的事实是该库已损坏,必须修复。 - 您正在将EAP组件包装到中,
Task
并正确使用await
。这可能会导致问题,因为EAP组件SynchronizationContext
直接与之交互。在这种情况下,最好的解决方案是修改类型,使其自然支持TAP或将其替换为TAP类型(例如HttpClient
代替WebClient
)。如果失败,则可以使用TAP上的TAP而不是EAP上的TAP。如果这两种方法都不可行,则可以Task.Run
在TAP-EAP-EAP包装器周围使用。
关于“忘了忘了”:
我个人从不使用此短语作为
async void方法。一方面,错误处理的语义最肯定不适合短语“即发即弃”。我开玩笑地将
asyncvoid方法称为“火灾和崩溃”。真正的
async“解雇”方法将是
async Task您忽略返回
Task而不是等待返回的方法。
就是说,在ASP.NET中,您几乎永远都不想从请求中早返回(这就是“一劳永逸”的含义)。这个答案已经太长了,但是我确实在博客上描述了这些问题,并在确实需要的情况下提供了一些支持ASP.NET“即弃即用”的代码。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)