API が非同期であるため、await
キーワードをブロックで使用できないという事実はcatch
、WinRT で非同期メソッドからのエラー メッセージを表示するのを非常に厄介にします。MessageDialog
理想的には、私はこれを書くことができるようにしたいと思います:
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
複数のブロックを模倣するために呼び出しを連鎖させることができます。
しかし、私はこの解決策に満足していません。構文は以前よりもさらに厄介です...