简体   繁体   中英

Convert Task to Task<T> (Wrap Task with return type of T)

I've read this question but in my case its simpler because I don't have to use Result property. so I was wondering if I can go with simpler approach than what is provided by Stephen Cleary's answer.

Suppose I have this simple interface.

internal interface IBinaryDataReadable
{
    Task Load(AsyncDataReader reader);
}

The interface provides method to load object asynchronously. it doesn't return anything since the load result is the object itself.

(The interface is internal and therefor implemented explicitly to avoid exposing implementation.)

Here is how I load binary data.

data = new BinaryData();
await ((IBinaryDataReadable)data).Load(reader);

I want to make this more fluent and verbose so I write this extension method

internal static Task<TData> Load<TData>(this TData data, AsyncDataReader reader)
    where TData : IBinaryDataReadable 
        => data.Load(reader).ContinueWith(t => data, TaskContinuationOptions.ExecuteSynchronously);

Now loading becomes like this.

data = await new BinaryData().Load(reader);

Is there anything here I should worry about using this method?, for example exception handling etc?

Th same could be done using async/await and foregoes using ContinueWith

internal static async Task<TData> Load<TData>(this TData data, AsyncDataReader reader) 
    where TData : IBinaryDataReadable {
    await data.Load(reader);
    return data;
}

That way you can even include exception handling within the method if so desired. The extension method however does not do much in terms of a fluent interface as the method returns a Task which would need awaiting.

And you would have to call the generic extension explicitly otherwise you are just calling the local member on the type which resolves to void when awaited causing a compile error.

data = await new BinaryData().Load<BinaryData>(reader); 

I would advise renaming the extension method to one that would not clash with the existing member on the interface.

data = await new BinaryData().LoadAsync(reader);

I wanted to know if use of ContinueWith introduces problems

I do not see it introducing any problems except for not being able to corral exceptions. But that can be managed by checking for that case and bubbling it up.

internal static Task<TData> LoadAsync<TData>(this TData data, AsyncDataReader reader)
    where TData : IBinaryDataReadable {
    return data.Load(reader)
        .ContinueWith(t => {
            var error = t.Exception;
            if (error != null && t.IsFaulted)
                throw error;
            return data;
        }, TaskContinuationOptions.ExecuteSynchronously);
}

Though, in my opinion, using async/await was a lot cleaner, easier to read and implement.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM