キャッチブロックで待つ


85

私は次のコードを持っています:

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ブロックの両方で待機呼び出しが許可される可能性があります

回答:


103

更新: C#6.0はawait incatchをサポートします


古い回答:フラグを使用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" ) );

7
svickに感謝します、それは非常に明白です、もっと良いもの、もっと非同期に接続されていますか?
ジェルジBalássy

そのようなものは存在しないと思います。
svick 2012年

3
あなたの場合、タスク継続を使用することもできます。しかし、svickの答えのコードは、継続を使用するコードよりもクリーンです。
Stephen Cleary 2012年

16
コールスタックを失うことなく例外を再スローする必要がある場合でも、System.Runtime.ExceptionServices.ExceptionDispatchInfo静的クラスを使用できます 。ExceptionDispatchInfo.Capture(ex)catchブロックを呼び出して、キャプチャされた例外である戻り値をローカル変数に格納するだけです。非同期コードを使い終わったらcapturedException.Throw()、元の例外を適切に再スローするを使用できます。
Etienne Maheu 2014

素晴らしいテクニック
Zia Ur Rahman


9

これはうまくいくようです。

        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;

6

これを試してみてください:

         try
        {
            await AsyncFunction(...);
        }

        catch(Exception ex)
        { 
            Utilities.LogExceptionToFile(ex).Wait();
            //instead of "await Utilities.LogExceptionToFile(ex);"
        }

Wait()エンディングを参照)


4

C#6.0を使用します。このリンクを参照してください

public async Task SubmitDataToServer()
{
  try
  {
    // Submit Data
  }
  catch
  {
    await LogExceptionAsync();
  }
  finally
  {
    await CloseConnectionAsync();
  }
}

1

フォールバックタスクを待機した後、例外を再スローするために使用するパターン:

ExceptionDispatchInfo capturedException = null;
try
{
  await SomeWork();
}
catch (Exception e)
{
  capturedException = ExceptionDispatchInfo.Capture(e);
}

if (capturedException != null)
{
  await FallbackWork();
  capturedException.Throw();
}

1

ラムダ式は次のように使用できます。

  try
    {
        //.....
    }
    catch (Exception ex)
    {
        Action<Exception> lambda;

        lambda = async (x) =>
        {
            // await (...);
        };

        lambda(ex);
    }

これによりラムダasync voidが作成されますが、必要がない限り使用しないでください。
svick 2017年

0

awaitキャッチブロックの後にlabel、を配置gotoし、トライブロックにを配置することができます。(いいえ、本当に!後藤はそれほど悪くはありません!)


0

同様の例で、私はキャッチブロックで待つことができませんでした。ただし、フラグを設定して、ifステートメントでフラグを使用することはできました(以下のコード)

---------------------------------------..。

boolean exceptionFlag = false; 

try 
{ 
do your thing 
} 
catch 
{ 
exceptionFlag = true; 
} 

if(exceptionFlag == true){ 
do what you wanted to do in the catch block 
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.