Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Casting a Task<T> to a Task<DerivedT>

I have a synchronous, generic method that looks like this

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

the proxy is a WCF service reference

It just has one method that takes a request and returns a response. But it is used by passing derived requests and returning derived responses. As you can see above the wrapper method is casting the response to the derived type specified by the generic parameter (TResponse).

You call the method with derived requests and responses

e.g.

Execute<GetSomeDataResponse>(new GetSomeDataRequest());

I am now generating an async service reference so can make use of Tasks

So I would like a method that looks like this

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

that can be called like this

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

So I need a way to cast the Task<Response> to a Task<TResponse>

I've been reading this which seems kind of the opposite of what I need, but cant quite figure out how to bend it to my use case

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

any ideas?

like image 227
ChrisCa Avatar asked May 13 '16 15:05

ChrisCa


People also ask

What's wrong with async void?

Async void methods can wreak havoc if the caller isn't expecting them to be async. When the return type is Task, the caller knows it's dealing with a future operation; when the return type is void, the caller might assume the method is complete by the time it returns.

Is an async method that returns task?

Async methods can have the following return types: Task, for an async method that performs an operation but returns no value. Task<TResult>, for an async method that returns a value. void , for an event handler.

How do I return a task in C#?

The recommended return type of an asynchronous method in C# is Task. You should return Task<T> if you would like to write an asynchronous method that returns a value. If you would like to write an event handler, you can return void instead. Until C# 7.0 an asynchronous method could return Task, Task<T>, or void.

What is task in asynchronous?

Asynchronous tasks run in the background and evaluate functions asynchronously when there is an event. Asynchronous tasks may run only until some work is completed, or they may be designed to run indefinitely. This tutorial describes how to interact with asynchronous tasks.


1 Answers

Easy way is use async\await pattern:

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

A bit more complicated (taken from your linked question) is to use 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;
}
like image 105
Evk Avatar answered Sep 29 '22 10:09

Evk