2017-08-27 60 views
2

我读过this question但在我的情况下它更简单,因为我不必使用Result属性。所以我想知道是否可以采用比斯蒂芬·克利里的答案更简单的方法。将任务转换为任务<T>(包装任务返回类型T)

假设我有这个简单的接口。

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

这里有什么我应该担心使用这种方法?例如异常处理等?

回答

4

钍同样可以使用异步完成/等待和foregoes使用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); 
} 

虽然在我看来,使用异步/等待是一个更清洁,更容易阅读和实施。

+0

谢谢。我避免使用async/await的原因是为了防止为非常基本的任务生成状态机开销,但这是一个很好的解决方案,我想知道是否使用ContinueWith引入了问题。 –

+1

@ M.kazemAkhgary,不,我没有看到它引入了任何问题,除了无法控制异常 – Nkosi

相关问题