此示例“失败”:
static async void Main(string[] args)
{
try
{
await TaskEx.Run(() => { throw new Exception("failure"); });
}
catch (Exception)
{
throw new Exception("success");
}
}
也就是说,文本“失败”的异常会冒泡。
然后我尝试了这个解决方法:
static async void Main(string[] args)
{
try
{
await SafeRun(() => { throw new Exception("failure"); });
}
catch (Exception)
{
throw new Exception("success");
}
}
static async Task SafeRun(Action action)
{
var ex = default(Exception);
await TaskEx.Run(() =>
{
try
{
action();
}
catch (Exception _)
{
ex = _;
}
});
if (ex != default(Exception))
throw ex;
}
这也没有帮助。
我想我的Async CTP刷新安装可能已经过了。
这段代码应该像我期望的那样工作(“成功”起泡,而不是“失败”),或者这不是“假设”以这种方式工作。如果没有,你会如何解决它?
答案 0 :(得分:5)
您看到的行为可能是边缘案例错误,甚至可能是正确的,如果不直观的话。通常,当您同步调用异步方法时,它会执行一个任务来执行,因为没有人等待任务完成,所以异常永远不会进入主线程。如果你直接调用Main会成功,但是你的运行时会在另一个线程上看到“成功”的例外。
由于main是应用程序的入口点,因此它会被同步调用,并且可能因为入口点不会触发Task包装行为,因此await不能正常运行并且TaskEx.Run会抛出自己的线程,在运行时显示为在另一个线程上抛出的异常。
如果你以async
方法运行main,即返回Task
(因为返回async
的{{1}}只能通过{{1}真正调用从同步主上下文中阻塞它,你会得到适当的行为,如下面的测试所示:
void
即。任务以await
错误,其中包含成功异常,因为它是内部异常。