Ben*_*sen 9 c# exception async-await c#-5.0
这个例子"失败":
static async void Main(string[] args)
{
try
{
await TaskEx.Run(() => { throw new Exception("failure"); });
}
catch (Exception)
{
throw new Exception("success");
}
}
Run Code Online (Sandbox Code Playgroud)
也就是说,文本"失败"的例外会冒泡.
然后我尝试了这个解决方法:
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;
}
Run Code Online (Sandbox Code Playgroud)
这也没有帮助.
我想我的Async CTP刷新安装可能会被清除.
这段代码应该像我期望的那样工作("成功"起泡,而不是"失败"),或者这不是"假设"以这种方式工作.如果没有,你会如何解决它?
您看到的行为可能是边缘案例错误,甚至可能是正确的,如果不直观.通常,当您同步调用异步方法时,它会执行一个任务来执行,因为没有人等待任务完成,所以异常永远不会进入主线程.如果你直接调用Main会成功,但是你的运行时会在另一个线程上看到"成功"的异常.
由于main是应用程序的入口点,因此它可以同步调用,因为入口点不会触发Task包装行为,因此await不能正常运行并且TaskEx.Run会抛出自己的线程,该线程显示在运行时作为异常被抛出另一个线程.
如果你将main作为一个async
方法运行,即返回一个Task
(因为一个async
返回void
只能真正调用via await
)并从同步主上下文中阻塞它,你会得到适当的行为,如下面的测试所示:
static async Task Main() {
try {
await TaskEx.Run(() => { throw new Exception("failure"); });
} catch(Exception) {
throw new Exception("success");
}
}
static async Task Main2() {
await Main();
}
[Test]
public void CallViaAwait() {
var t = Main2();
try {
t.Wait();
Assert.Fail("didn't throw");
} catch(AggregateException e) {
Assert.AreEqual("success",e.InnerException.Message);
}
}
[Test]
public void CallDirectly() {
var t = Main();
try {
t.Wait();
Assert.Fail("didn't throw");
} catch(AggregateException e) {
Assert.AreEqual("success", e.InnerException.Message);
}
}
Run Code Online (Sandbox Code Playgroud)
即任务故障,AggregateException
其中包含成功异常,因为它是内部异常.