我们无法在await
块中使用catch
关键字,这使得在WinRT中显示来自异步方法的错误消息非常尴尬,因为MessageDialog
API是异步的。理想情况下,我希望能够写下这个:
private async Task DoSomethingAsync()
{
try
{
// Some code that can throw an exception
...
}
catch (Exception ex)
{
var dialog = new MessageDialog("Something went wrong!");
await dialog.ShowAsync();
}
}
但我必须这样写:
private async Task DoSomethingAsync()
{
bool error = false;
try
{
// Some code that can throw an exception
...
}
catch (Exception ex)
{
error = true;
}
if (error)
{
var dialog = new MessageDialog("Something went wrong!");
await dialog.ShowAsync();
}
}
所有需要这样做的方法必须遵循类似的模式,我真的不喜欢它,因为它会降低代码的可读性。
有没有更好的方法来解决这个问题?
编辑:我想出了这个(这与svick在评论中建议的相似):
static class Async
{
public static async Task Try(Func<Task> asyncAction)
{
await asyncAction();
}
public static async Task Catch<TException>(this Task task, Func<TException, Task> handleExceptionAsync, bool rethrow = false)
where TException : Exception
{
TException exception = null;
try
{
await task;
}
catch (TException ex)
{
exception = ex;
}
if (exception != null)
{
await handleExceptionAsync(exception);
if (rethrow)
ExceptionDispatchInfo.Capture(exception).Throw();
}
}
}
用法:
private async Task DoSomethingAsync()
{
await Async.Try(async () =>
{
// Some code that can throw an exception
...
})
.Catch<Exception>(async ex =>
{
var dialog = new MessageDialog("Something went wrong!");
await dialog.ShowAsync();
});
}
.Catch<...>
次调用可以链接到模仿多个catch
块。
但我对这个解决方案并不满意;语法比以前更尴尬......
答案 0 :(得分:1)
您已在TPL中拥有该功能
await Task.Run(async () =>
{
// Some code that can throw an exception
...
}).ContinueWith(async (a) =>
{
if (a.IsFaulted)
{
var dialog = new MessageDialog("Something went wrong!\nError: "
+ a.Exception.Message);
await dialog.ShowAsync();
}
else
{
var dialog2 = new MessageDialog("Everything is OK: " + a.Result);
await dialog2.ShowAsync();
}
}).Unwrap();
在这台机器上,我没有Windows 8,所以我在Windows 7中进行了测试,但我认为是相同的。 *编辑 正如评论所述,需要.Unwrap();最终等待工作
答案 1 :(得分:0)
C#6现在支持await
和catch
中的finally
,因此代码可以按照我想要的方式编写;不再需要解决方法。