私は次のコードを持っています:
WebClient wc = new WebClient();
string result;
try
{
result = await wc.DownloadStringTaskAsync( new Uri( "http://badurl" ) );
}
catch
{
result = await wc.DownloadStringTaskAsync( new Uri( "http://fallbackurl" ) );
}
基本的に、URLからダウンロードし、例外で失敗した場合は、別のURLからダウンロードしたいと思います。もちろん、両方の時間は非同期です。ただし、コードはコンパイルされません。
エラーCS1985:catch句の本文で待機できません
OK、何らかの理由で禁止されていますが、ここでの正しいコードパターンは何ですか?
編集:
良いニュースは、 C#6.0はcatchブロックとfinallyブロックの両方でawait呼び出しを許可する可能性が高い です。
古い回答:フラグを使用して、await
ブロックからcatch
を移動するようにそのコードを書き換えることができます。
WebClient wc = new WebClient();
string result = null;
bool downloadSucceeded;
try
{
result = await wc.DownloadStringTaskAsync( new Uri( "http://badurl" ) );
downloadSucceeded = true;
}
catch
{
downloadSucceeded = false;
}
if (!downloadSucceeded)
result = await wc.DownloadStringTaskAsync( new Uri( "http://fallbackurl" ) );
Roslynのエンドユーザープレビューの時点で、catchブロックでの待機が可能になりました ここに示されているように(catch/finallyのAwaitの下にリストされています そしてC#6に含まれます。
リストされている例は
try … catch { await … } finally { await … }
更新:新しいリンクを追加し、C#6になります
これはうまくいくようです。
WebClient wc = new WebClient();
string result;
Task<string> downloadTask = wc.DownloadStringTaskAsync(new Uri("http://badurl"));
downloadTask = downloadTask.ContinueWith(
t => {
return wc.DownloadStringTaskAsync(new Uri("http://google.com/")).Result;
}, TaskContinuationOptions.OnlyOnFaulted);
result = await downloadTask;
これを試してみてください:
_ try
{
await AsyncFunction(...);
}
catch(Exception ex)
{
Utilities.LogExceptionToFile(ex).Wait();
//instead of "await Utilities.LogExceptionToFile(ex);"
}
_
(Wait()
の終わりを参照)
C#6.0を使用します。こちらをご覧ください リンク
public async Task SubmitDataToServer()
{
try
{
// Submit Data
}
catch
{
await LogExceptionAsync();
}
finally
{
await CloseConnectionAsync();
}
}
フォールバックタスクの待機後に例外を再スローするために使用するパターン:
ExceptionDispatchInfo capturedException = null;
try
{
await SomeWork();
}
catch (Exception e)
{
capturedException = ExceptionDispatchInfo.Capture(e);
}
if (capturedException != null)
{
await FallbackWork();
capturedException.Throw();
}
次のようにラムダ式を使用できます。
try
{
//.....
}
catch (Exception ex)
{
Action<Exception> lambda;
lambda = async (x) =>
{
// await (...);
};
lambda(ex);
}
同様の例では、catchブロックで待つことができませんでした。ただし、フラグを設定し、ifステートメントでフラグを使用することができました(以下のコード)
---------------------------------------...
boolean exceptionFlag = false;
try
{
do your thing
}
catch
{
exceptionFlag = true;
}
if(exceptionFlag == true){
do what you wanted to do in the catch block
}
Catchブロックの後にawait
を配置し、その後にlabel
を配置し、tryブロックにgoto
を配置できます。 (いいえ、本当に!後藤はそんなに悪くない!)