我想知道为什么异常处理在asp.net和控制台中对async / await调用的行为有所不同。考虑这种方法:
private static async Task Test()
{
try
{
await Task.Run(() =>
{
throw new Exception("Test Exception");
});
}
catch (Exception)
{
throw;
}
}
Catch没有在IIS下工作的ASP.NET非异步控制器,在Test()和TestAction()中都没有:
[HttpGet]
public virtual ActionResult TestAction()
{
try
{
Test().Wait();
}
catch (Exception)
{
throw;
}
}
而是http请求挂起。相同的控制台代码或WindowsForms代码在两个地方都能正常工作:
class Program
{
static void Main(string[] args)
{
try
{
Test().Wait();
}
catch (Exception)
{
throw;
}
}
}
更新:
这段代码在asp.net控制器中工作正常(catch被调用):
[HttpGet]
public virtual ActionResult TestAction()
{
try
{
Task.Run(() =>
{
throw new Exception("Test Exception");
}).Wait();
}
catch (Exception)
{
throw;
}
}
答案 0 :(得分:1)
TestAction()
调用Test()
同步运行,直到Task.Run....
然后await
放弃当前线程。 Wait()
中的TestAction()
现在接受该线程并阻止它直到任务完成。同时,任务抛出并完成。控件应该返回到await
之后的行,但它不能,因为它想要将控制权返回给它被调用的线程,该线程被阻塞。因此,僵局。 ConfigureAwait(false)
告诉它可以在与原始线程不同的线程上返回控制,从而允许TestAction()
完成。
它在控制台应用程序中运行良好,因为他们没有SynchronizationContext
坚持将控制权返回给原始线程。 WPF和asp.net具有该自定义同步上下文,因为必须从调用线程进行更改。