假设我想确保由于调用者的取消请求,从异步方法返回的任务对象将转换为已取消状态。
Catch is:无论上述方法消耗的异步方法是如何实现的,以及它们是否完成,都应该发生这种情况。
考虑以下扩展方法:
public static Task<T> ToTask<T>(this CancellationToken cancellationToken)
{
var tcs = new TaskCompletionSource<T>();
cancellationToken.Register(() => { tcs.SetCanceled(); });
return tcs.Task;
}
我现在可以使用这样的任务来确保上述情况:
public async Task<Item> ProvideItemAsync(CancellationToken cancellationToken)
{
Task<Item> cancellationTask = cancellationToken.ToTask<Item>();
Task<Item> itemTask = _itemProvider.ProvideItemAsync(cancellationToken);
Task<Task<Item>> compoundTask = Task.WhenAny(cancellationTask, itemTask);
Task<Item> finishedTask = await compoundTask;
return await finishedTask;
}
我的问题是:
1)这种方法有什么问题吗?
2)是否有内置的API来促进这种用例
谢谢!
答案 0 :(得分:4)
假设我想确保取消异步操作, 无论实际操作如何实施以及是否完成。
除非将代码封装到单独的进程中,否则这是不可能的。
当我说&#34;确保&#34;时,我的意思是说表示所述操作的任务转换为已取消状态。
如果你只想取消任务(而不是操作本身),那么你可以这样做。
这种方法有什么问题吗?
这里有一些棘手的边缘案例。特别是,如果任务成功完成,则需要处理Register
的结果。
我建议使用WaitAsync
extension method中的AsyncEx.Tasks
library:
public Task<Item> ProvideItemAsync(CancellationToken cancellationToken)
{
return _itemProvider.ProvideItemAsync(cancellationToken).WaitAsync(cancellationToken);
}