0

내가 dollowing의 C# 5 의사에 해당 할 노력하고있어 기다리고 도서관 병렬 -번역 예외 라

async Task<int> CallAndTranslate() 
{ 
    try 
    { 
     return await client.CallAsync(); 
    } catch(FaultException ex) { 
     if (ex.FaultCode ...) 
      throw new Exception("translated"); 
    } 
} 

Given an arbitrary Taskwhich does not return a result, translating exceptions는 C# 5 백 포팅 쉽게 using the technique supplied by @Drew Marsh

Task.ContinueWith의 과부하로이 기술은 보통 Task<T>으로 일반화되지 않습니다. Task이 아니라 Task<T>이 아니라 대머리가 반환됩니다. 관통 던져 잡힐의 음모를 통과 할 수있는 예외를 일으키는 또 다른 Task<T>

  • 에 포장

    • :

      에 의존하지 않고 TPL API를 사용하여이를 달성 할 수있는 방법이 있나요 예외 처리 메커니즘 예외가

    • ,691,363를 번역 할 수없는 경우 단독 스택 추적을 떠나야한다 intial 대답 한 후
    • ADDED ....

      public class TranslatingExceptions 
      { 
          Task<int> ApiAsync() 
          { 
           return Task<int>.Factory.StartNew(() => { 
            throw new Exception("Argument Null"); }); 
          } 
      
          public Task<int> WrapsApiAsync() 
          { 
           return ApiAsync().TranslateExceptions(x=>{ 
            if (x.Message == "Argument Null") 
             throw new ArgumentNullException(); 
           }); 
          } 
      
          [Fact] 
          public void Works() 
          { 
           var exception = Record.Exception(() => 
            WrapsApiAsync().Wait()); 
           Assert.IsType<ArgumentNullException>(exception.InnerException); 
          } 
      } 
      

      다음 Task<T> 확장 내 자리 구현 구현 :


    210 여기 내 순진 자리 구현의

    static class TaskExtensions 
    { 
        public static Task<T> TranslateExceptions<T>(this Task<T> task, Action<Exception> translator) 
        { 
        // TODO REPLACE NAIVE IMPLEMENTATION HERE 
         return Task<T>.Factory.StartNew(() => 
         { 
          try 
          { 
           return task.Result; 
          } 
          catch (AggregateException exception) 
          { 
           translator(exception.InnerException); 
           throw; 
          } 
         }); 
        } 
    } 
    
  • 답변

    2

    당신은 반복자를 사용하여 .NET 4.0 await을 모방 할 수 있습니다 (yield를) ,하지만 꽤 아니야.

    상태 시스템이 없으면 작업이 완료 될 때까지 호출자에게 제어권을 반환하고 실행 만 계속할 때까지 await의 전체 지점이 누락됩니다.

    음, 아마도 나는을 놓쳤습니다!

    public Task<int> ApiAsync() // The inner layer exposes it exactly this way 
    { 
        return Task<int>.Factory.StartNew(() => 
         { throw new Exception("Argument Null"); }); 
    } 
    
    // this layer needs to expose it exactly this way 
    public Task<int> WrapsApiAsync() 
    { 
        // Grab the task that performs the "original" work 
        Task<int> apiAsyncTask = ApiAsync(); 
    
        // Hook a continuation to that task that will do the exception "translation" 
        Task<int> result = apiAsyncTask.ContinueWith(antecedent => 
        { 
         // Check if the antecedent faulted 
         // If so check what the exception's message was 
         if (antecedent.IsFaulted) 
         { 
          if (antecedent.Exception.InnerException.Message == "Argument Null") 
          { 
           throw new ArgumentNullException(); 
          } 
    
          throw antecedent.Exception.InnerException; 
         } 
    
         return antecedent.Result; 
        }, 
        TaskContinuationOptions.ExecuteSynchronously); 
    
        // Now we return the continuation Task from the wrapper method 
        // so that the caller of the wrapper method waits on that 
        return result; 
    } 
    

    UPDATE : 샘플 응답에 대한 TaskCompletionSource

    public static Task<int> WrapsApiAsync() 
    { 
        var tcs = new TaskCompletionSource<int>(); 
    
        Task<int> apiAsyncTask = ApiAsync(); 
    
        apiAsyncTask.ContinueWith(t => 
         { 
          switch (t.Status) 
          { 
           case TaskStatus.RanToCompletion: 
            tcs.SetResult(task.Result); 
            break; 
    
           case TaskStatus.Canceled: 
            tcs.SetCanceled(); 
            break; 
    
           case TaskStatus.Faulted: 
    
            if (t.Exception.InnerException.Message == "Argument Null") 
            { 
             try 
             { 
              throw new ArgumentNullException(); 
             } 
             catch (ArgumentNullException x) 
             { 
              tcs.SetException(x); 
             } 
            } 
            else 
            { 
             tcs.SetException(t.Exception.InnerException); 
            } 
    
            break; 
          } 
         } 
        ); 
    
        return tcs.Task; 
    } 
    
    +0

    감사를 사용하여 당신은 단지 ContinueWith<T>를 사용하려는 경우 드류 마쉬의 코드 단지 약간의 비틀기입니다. 불행하게도 질문에 언급 된 ** Task **'.ContinueWith'는'Task '을 반환하지 않으므로 여기에 문제가 있습니다. 그러므로 질문을 던지며 (놀랍지 않게도 나위도하지 않습니다). 아마도 ToTaskOf 변환기가 있습니다. 어느 쪽이든, 이것은 제공된 테스트 베드에서 통과하지 않을 것입니다, 미안 해요! (내가 복제하려고하는 비트는 상태 머신이 수행하는 것이 아니라 'Task '저글링입니다.) 작년부터 @ 존 켓 (Jon Skeet)의 뛰어난 'C# 5에서의 비동기식 파괴'시리즈의 내용은 기억이 안납니다. –

    +0

    MSDN은'ContinueWith'의 모든 과부하를 표시하지는 않지만 확실히'Task '을 반환하는 것들이 있습니다. [This one] (http://msdn.microsoft.com/en-us/library/dd321561.aspx)이 가장 비슷하지만 '작업 '을 전제로 사용하는 .NET 4 RTM에도 있습니다. –

    +0

    수정하십시오.명확하지는 않지만 연속 메서드에서 결과를 반환하면 컴파일러에서 작업 의 결과로 적절한 오버로드를 선택합니다. –