簡體   English   中英

在重寫同步代碼以使用TPL時如何簡化或包裝異常

[英]How to simplify or wrap exceptions when rewriting synchronous code to use TPL

鑒於實施如下:

public class SomeServiceWrapper
{
    public string GetSomeString()
    {
        try
        {
            //Do Something
        }
        catch (IOException e)
        {
            throw new ServiceWrapperException("Some Context", e);
        }
        catch (WebException e)
        {
            throw new ServiceWrapperException("Some Context", e);
        }
    }
}

上述目的是使GetSomeString的使用者只需要捕獲ServiceWrapperException

請考慮以下方法以使用類似的異步行為來擴展它:

public Task<string> GetSomeStringAsync()
{
    Task<string>.Factory doSomething = ...
    return doSomething.ContinueWith(x => 
    {
        if (x.IsFaulted)
        {
             if (x.Exception.InnerExceptions.Count() > 1)
             {
                 throw new AggregateException(x.Exception);
             }

             var firstException = x.Exception.InnerExceptions[0];
             if (typeof(firstException) == typeof(IOException)
                 || typeof(firstException) == typeof(WebException))
             {
                 throw new ServiceWrapperException("Some Context", firstException);
             }
        }

        return x.Result;
    }
} 

這種包裝異常的同步方法自然不適合異步方法。

SomeServiceWrapper的作者可以做些什么來簡化任何消費者的異常處理代碼,這樣他們只需要處理TradeLoaderException而不是IOExceptionWebException

我做了一個擴展方法,幾乎​​就是這樣。 用法:

public static Task<string> GetSomeStringAsync()
{
    var doSomething = Task.Factory.StartNew(() => "bar");
    return doSomething.WrapExceptions(typeof(IOException), typeof(WebException));
}
  1. 您可以使用延續返回原始任務。
  2. 我建議更改ServiceWrapperException以保存多個異常,如AggregateException,然后更改第一部分。

方法:

public static Task<TResult> WrapExceptions<TResult>(this Task<TResult> task, params Type[] exceptionTypes)
{
    return task.ContinueWith(_ =>
    {
        if (_.Status == TaskStatus.RanToCompletion) return _.Result;

        if (_.Exception.InnerExceptions.Count > 1)
        {
            throw new AggregateException(_.Exception);
        }

        var innerException = _.Exception.InnerExceptions[0];
        if (exceptionTypes.Contains(innerException.GetType()))
        {
            throw new ServiceWrapperException("Some Context", innerException);
        }

        throw _.Exception;
    });
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM