catch 블록에서 대기


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

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

편집하다:

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

답변:


103

업데이트 : 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" ) );

7
감사합니다 svick, 그것은 아주 명백하고, 더 나은 것, 비동기에 더 연결되어 있습니까?
György Balássy

나는 그런 것은 존재하지 않는다고 생각합니다.
svick

3
귀하의 경우 작업 연속을 사용할 수도 있습니다. 그러나 svick의 답변 의 코드는 연속을 사용하는 코드보다 깨끗합니다.
Stephen Cleary 2012 년

16
호출 스택을 잃지 않고 예외를 다시 던져야하는 경우에도 System.Runtime.ExceptionServices.ExceptionDispatchInfo정적 클래스를 사용할 수 있습니다 . ExceptionDispatchInfo.Capture(ex)catch 블록을 호출 하고 캡처 된 예외 인 반환 값을 로컬 변수에 저장하기 만하면 됩니다. 비동기 코드로 작업을 마치면 capturedException.Throw()원래 예외를 올바르게 다시 throw하는 것을 사용할 수 있습니다 .
Etienne Maheu 2014-08-08

멋진 기술
지 아우르 라흐만


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

0

당신은 넣을 수 await다음에 catch 블록 후 label,과를 넣어 gototry 블록에서. (아니, 정말! 고토는 그렇게 나쁘지 않아!)


0

비슷한 경우에 나는 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 
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.