繁体   English   中英

将任务转换为任务 <T> (包装任务,返回类型为T)

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

我已经阅读了这个问题,但就我而言,它比较简单,因为我不必使用Result属性。 所以我想知道是否可以采用比Stephen Cleary的答案所提供的方法更简单的方法。

假设我有这个简单的界面。

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

该接口提供了异步加载对象的方法。 它不会返回任何内容,因为加载结果是对象本身。

(该接口是内部的,因此明确地实现了该接口以避免公开实现。)

这是我加载二进制数据的方式。

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

我想让它更流畅和冗长,所以我写了这个扩展方法

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

现在加载变得像这样。

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

这里是否有我需要担心使用此方法的问题?例如异常处理等?

可以使用async / await完成此操作,并使用ContinueWith放弃

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

这样,如果需要,您甚至可以在方法中包括异常处理。 但是,扩展方法在流畅的界面方面做不到很多,因为该方法返回需要等待的Task。

而且,您将必须显式地调用通用扩展名,否则,您将仅调用该类型的本地成员,该类型将在等待导致编译错误时解析为void

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

我建议将扩展方法重命名为不会与接口上现有成员冲突的扩展方法。

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

我想知道使用ContinueWith是否会带来问题

我看不到它不会带来任何问题,除非无法确保异常。 但这可以通过检查这种情况并冒泡进行管理。

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);
}

虽然在我看来,使用async / await更加整洁,更易于阅读和实现。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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