将任务<t>转换为任务<derivedt>

时间:2016-05-13 15:10:06

标签: c# asynchronous task

我有一个看起来像这样的同步通用方法

public TResponse Execute<TResponse>(Request request) where TResponse : Response
{
   return (TResponse) proxy.ExecuteRequest(request);

代理是WCF服务引用

它只有一个接收请求并返回响应的方法。但它通过传递派生请求和返回派生响应来使用。如上所示,wrapper方法将响应转换为泛型参数(TResponse)指定的派生类型。

您使用派生的请求和响应调用方法

e.g。

Execute<GetSomeDataResponse>(new GetSomeDataRequest());

我现在正在生成异步服务引用,因此可以使用任务

所以我想要一个看起来像这样的方法

public Task<TResponse> ExecuteAsync<TResponse>(Request request) where TResponse : Response
{
    // need to cast to a Task<TResponse>
    return proxy.ExecuteRequestAsync(request

可以像这样调用

Task<GetSomeDataResponse> res = ExecuteAsync<GetSomeDataResponse>(new GetSomeDataRequest());

所以我需要一种方法将Task<Response>转换为Task<TResponse>

我一直在阅读这个看起来与我需要的相反,但是无法弄清楚如何将它弯曲到我的用例

How to convert a Task<TDerived> to a Task<TBase>?

任何想法?

1 个答案:

答案 0 :(得分:2)

简单方法是使用async \ await pattern:

 public static async Task<TResponse> ExecuteAsync<TResponse>(Request request) where TResponse : Response {
    var response = await proxy.ExecuteRequestAsync(request);
    return (TResponse) response;
 }

有点复杂(取自你的链接问题)是使用TaskCompletionSource

public static Task<TResponse> ExecuteAsync2<TResponse>(Request request) where TResponse : Response {
    var tcs = new TaskCompletionSource<TResponse>();
    proxy.ExecuteRequestAsync(request).ContinueWith(t => {
        if (t.IsFaulted)
            tcs.TrySetException(t.Exception.InnerExceptions);
        else if (t.IsCanceled)
            tcs.TrySetCanceled();
        else
            tcs.TrySetResult((TResponse) t.Result);
        }, TaskContinuationOptions.ExecuteSynchronously);
    return tcs.Task;
}