问题为异步库创建通用包装器

时间:2014-02-19 18:43:16

标签: c# generics asynchronous

我有一个类库https://github.com/trydis/FIFA-Ultimate-Team-2014-Toolkit我想创建一个包装器,而不是只调用FutClient我想创建一个FutClientWrapper,我可以处理异常,reloggin和loggin我要包装的接口是{{ 3}}

所以我做了https://github.com/trydis/FIFA-Ultimate-Team-2014-Toolkit/blob/master/UltimateTeam.Toolkit/IFutClient.cs

代码段

    public async Task<AuctionResponse> SearchAsync(SearchParameters searchParameters)
    {
        return await Invoke(f => f.SearchAsync(searchParameters), searchParameters);
    }

    public async Task<AuctionResponse> PlaceBidAsync(AuctionInfo auctionInfo, uint bidAmount = 0)
    {
        return await Invoke(f => f.PlaceBidAsync(auctionInfo, bidAmount), auctionInfo);
    }

    public async Task<Item> GetItemAsync(long resourceId)
    {
        return await Invoke(f => f.GetItemAsync(resourceId), resourceId);
    }

    public TResult Invoke<TResult>(Func<FutClient, TResult> func, object requestDetails = null,
        [CallerMemberName] string exceptionMessage = null)
    {
        try
        {
            if (LastException + new TimeSpan(0, 0, 30) < DateTime.Now)
            {
                TResult result = func(_futClient);
                return result;
            }
        }
        catch (Exception e)
        {

这里我尝试包装并捕获Futclient中抛出的任何异常,但是我在例如此行中得到一个空异常

   return await Invoke(f => f.GetItemAsync(resourceId), resourceId);

似乎是因为我的

TResult result = func(_futClient);
                return result;

不运行异步,它只返回一个空响应(所有空值)

因此我将其更改为http://pastebin.com/0EJdCbbr

代码段:

    public async Task<AuctionResponse> GetTradePileAsync()
    {
        return await NewInvoke<AuctionResponse>(new Task<object>(() => _futClient.GetTradePileAsync()));
    }

    public async Task<WatchlistResponse> GetWatchlistAsync()
    {
        return await NewInvoke<WatchlistResponse>(new Task<object>(() => _futClient.GetWatchlistAsync()));
    }

    public async Task<TResult> NewInvoke<TResult>(Task<object> taskToRun) where TResult : class
    {
        try
        {
            taskToRun.Start();
            Task.WaitAll(taskToRun);
            return taskToRun.Result as TResult;
        }
        catch (AggregateException ex)
        {
            //ex.InnerException
            return null;
        }
        catch (Exception e)
        {
            return null;

        }
    }

但是在这里我在调用方法之外得到了异常

那么我应该如何做到这一点,它将任务和任务作为一个响应类型处理并获取x个参数

然后它应该在Invoke方法中抛出任何异常,所以我只有一个需要捕获异常的地方

1 个答案:

答案 0 :(得分:1)

在返回之前,你必须在try块内await,否则捕获的异常就不会发生。你的第一次尝试实际上更接近正确的方法。

public async Task<TResult> Invoke<TResult>(Func<FutClient, Task<TResult>> func, object requestDetails = null,
    [CallerMemberName] string exceptionMessage = null)
{
    try
    {
        if (LastException + new TimeSpan(0, 0, 30) < DateTime.Now)
        {
            TResult result = await func(_futClient).ConfigureAwait(false); //Here we both await for the result and set `ConfigureAwait` to false so we don't need to waist extra time trying to marshal back on to the original Synchronization context as we have no need for it for the rest of the method.
            return result;
        }
    }
    catch (Exception e)
    {
        //...

然后您就像使用以下

一样使用它
public Task<AuctionResponse> PlaceBidAsync(AuctionInfo auctionInfo, uint bidAmount = 0)
{
    return Invoke(f => f.PlaceBidAsync(auctionInfo, bidAmount), auctionInfo);
}

此外部函数不需要await,您可以直接返回Invoke返回的任务