[c#] 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 절 본문에서 기다릴 수 없습니다.

좋아, 어떤 이유로 든 금지되어 있지만 여기서 올바른 코드 패턴은 무엇입니까?

편집하다:

좋은 소식은 C # 6.0이 catch 및 finally 블록 모두에서 await 호출을 허용한다는 것 입니다.



답변

업데이트 : C # 6.0은 Await in 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" ) );


답변

여기에 표시된대로 Roslyn의 최종 사용자 미리보기 (catch / finally에 Await 아래 나열)에서 catch 블록에서 대기하는 것이 가능하며 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);
    }