我有这样的情况:
private Task LongRunningTask = /* Something */;
private void DoSomethingMore(Task previousTask) { }
public Task IndependentlyCancelableSuccessorTask(CancellationToken cancellationToken)
{
return LongRunningTask.ContinueWith(DoSomethingMore, cancellationToken);
}
特别是,我在这里感兴趣的行为详细描述在MSDN 有关延续任务的页面 http://msdn.microsoft.com/en-us/library/ee372288.aspx具体如下:
继续进入Canceled
在这些场景中声明:
- [...]
- 当延续被传递时System.Threading.CancellationToken http://msdn.microsoft.com/en-us/library/system.threading.cancellationtoken.aspx作为一个论点和IsCancellationRequested http://msdn.microsoft.com/en-us/library/system.threading.cancellationtoken.iscancellationrequested.aspx令牌的属性是
true
在继续运行之前。在这种情况下,延续不会开始,而是过渡到Canceled http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskstatus.aspx state.
上面的代码有效。然而,我正在将尽可能多的延续转换为使用await
关键词。
是否有等效的使用await
这将允许在等待的任务完成之前取消继续?
尽管看起来有点尴尬,但应该执行以下操作:
private Task LongRunningTask = /* Something */;
private void DoSomethingMore() { }
public async Task IndependentlyCancelableSuccessorTask(
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var tcs = new TaskCompletionSource<bool>();
using (cancellationToken.Register(() => tcs.TrySetCanceled()))
await Task.WhenAny(LongRunningTask, tcs.Task);
cancellationToken.ThrowIfCancellationRequested();
DoSomethingMore();
}
[UPDATE]根据 svick 的建议,这里将其塑造为一个助手,基于 Stephen Toub 的使用 Await 实现 then http://blogs.msdn.com/b/pfxteam/archive/2012/08/15/implementing-then-with-await.aspx图案:
public static class TaskExt
{
/// <summary>
/// Use: await LongRunningTask.Then(DoSomethingMore, cancellationToken)
/// </summary>
public static async Task Then(
this Task antecedent, Action continuation, CancellationToken token)
{
await antecedent.When(token);
continuation();
}
/// <summary>
/// Use: await LongRunningTask.When(cancellationToken)
/// </summary>
public static async Task When(
this Task antecedent, CancellationToken token)
{
token.ThrowIfCancellationRequested();
var tcs = new TaskCompletionSource<Empty>();
using (token.Register(() => tcs.TrySetCanceled()))
await Task.WhenAny(antecedent, tcs.Task);
token.ThrowIfCancellationRequested();
}
struct Empty { };
}
也许,第一个ThrowIfCancellationRequested()
是多余的,但我还没有彻底考虑所有边缘情况。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)