web-dev-qa-db-ja.com

catchブロックで待機

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

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呼び出しを許可する可能性が高い です。

82

更新:C#6.0はcatchでの待機をサポート


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

Roslynのエンドユーザープレビューの時点で、catchブロックでの待機が可能になりました ここに示されているように(catch/finallyのAwaitの下にリストされています そしてC#6に含まれます。

リストされている例は

try … catch { await … } finally { await … }

更新:新しいリンクを追加し、C#6になります

24
Craig

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

        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;
9
Darragh

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

_         try
        {
            await AsyncFunction(...);
        }

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

Wait()の終わりを参照)

5
Ron

C#6.0を使用します。こちらをご覧ください リンク

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

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

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

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

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

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

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

        lambda(ex);
    }
1
Izmoto

同様の例では、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 
}
0
Amanda Berenice

Catchブロックの後にawaitを配置し、その後にlabelを配置し、tryブロックにgotoを配置できます。 (いいえ、本当に!後藤はそんなに悪くない!)

0
Protector one