【问题标题】:Convert Task to Task<T> (Wrap Task with return type of T)将 Task 转换为 Task<T>(使用 T 的返回类型包装 Task)
【发布时间】:2017-08-27 15:58:54
【问题描述】:

我读过this question,但在我的情况下它更简单,因为我不必使用Result 属性。所以我想知道我是否可以采用比 Stephen Cleary 的回答提供的更简单的方法。

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

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

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

(接口是内部的,因此显式实现以避免暴露实现。)

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

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

我想让这个更流畅和详细,所以我写了这个 extension 方法

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

这里有什么我需要担心的吗?例如异常处理等?

【问题讨论】:

    标签: c# generics task continuewith


    【解决方案1】:

    同样可以使用 async/await 并放弃使用 ContinueWith

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

    如果需要,您甚至可以在方法中包含异常处理。 然而,扩展方法在流畅的接口方面并没有做太多的事情,因为该方法返回一个需要等待的任务。

    而且您必须显式调用泛型扩展,否则您只是在等待时调用解析为 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 更简洁,更易于阅读和实现。

    【讨论】:

    • 谢谢。我避免使用 async/await 的原因是为了防止为非常基本的任务生成状态机开销,尽管这是一个很好的解决方案,我想知道使用 ContinueWith 是否会引入问题。
    • @M.kazemAkhgary,不。除了无法控制异常之外,我认为它不会引入任何问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-24
    • 2016-09-23
    • 1970-01-01
    相关资源
    最近更新 更多