【发布时间】:2017-03-08 20:41:02
【问题描述】:
假设我想确保从异步方法返回的任务对象由于调用者的取消请求而转换为取消状态。
关键是:无论上述方法使用的异步方法如何实现以及它们是否完成,都应该发生这种情况。
考虑以下扩展方法:
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 来促进这样的用例
谢谢!
【问题讨论】:
-
是
rawImageTask还是itemTask?itemTask当前是未使用的本地。 -
@spender 抱歉,那个人逃过了编辑。
-
“不管实际操作如何实现”是不可能的。任务取消是一个合作过程;如果任务在被取消时没有检查任何地方,则它实际上不会被取消。当然,在这种情况下,您仍然可以随意忽略结果并说它被取消了——但它会继续在后台运行。
-
@JeroenMostert。你是对的,但我可以确保的是,客户的取消请求不会被完全忽略,这有时是至关重要的。我已经修改了我的问题以进一步说明我的意图。
-
您的
ToTask方法存在问题,这对于使用Register的任何方法都很常见;这会泄漏资源。有关更多信息(以及一些建议的解决方案),请参阅this question。包括指向this 的链接,这似乎实现了您所追求的。
标签: c# asynchronous task-parallel-library cancellation