M.k*_*ary 2 c# generics task continuewith
我已经读过这个问题,但就我而言,它更简单,因为我不必使用Result属性。所以我想知道我是否可以采用比斯蒂芬·克利里的答案提供的更简单的方法。
假设我有这个简单的界面。
internal interface IBinaryDataReadable
{
Task Load(AsyncDataReader reader);
}
Run Code Online (Sandbox Code Playgroud)
该接口提供了异步加载对象的方法。它不返回任何内容,因为加载结果是对象本身。
(该接口是内部的,因此显式实现以避免暴露实现。)
这是我加载二进制数据的方法。
data = new BinaryData();
await ((IBinaryDataReadable)data).Load(reader);
Run Code Online (Sandbox Code Playgroud)
我想让它更加流畅和详细,所以我编写了这个扩展方法
internal static Task<TData> Load<TData>(this TData data, AsyncDataReader reader)
where TData : IBinaryDataReadable
=> data.Load(reader).ContinueWith(t => data, TaskContinuationOptions.ExecuteSynchronously);
Run Code Online (Sandbox Code Playgroud)
现在加载就变成这样了。
data = await new BinaryData().Load(reader);
Run Code Online (Sandbox Code Playgroud)
使用此方法有什么我应该担心的吗?例如异常处理等?
同样可以使用 async/await 来完成,并放弃使用ContinueWith
internal static async Task<TData> Load<TData>(this TData data, AsyncDataReader reader)
where TData : IBinaryDataReadable {
await data.Load(reader);
return data;
}
Run Code Online (Sandbox Code Playgroud)
这样,如果需要,您甚至可以在方法中包含异常处理。然而,扩展方法在流畅的接口方面并没有做太多事情,因为该方法返回一个需要等待的任务。
并且您必须显式调用通用扩展,否则您只是调用类型上的本地成员,该类型将解析为voidwhen waiting 导致编译错误。
data = await new BinaryData().Load<BinaryData>(reader);
Run Code Online (Sandbox Code Playgroud)
我建议将扩展方法重命名为不会与界面上现有成员冲突的方法。
data = await new BinaryData().LoadAsync(reader);
Run Code Online (Sandbox Code Playgroud)
我想知道使用是否会
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);
}
Run Code Online (Sandbox Code Playgroud)
不过,在我看来,使用 async/await 更干净、更容易阅读和实现。