ContinueWith(委托的CancellationToken)与等待延续等效 [英] Equivalent of ContinueWith(delegate, CancellationToken) with await continuation

查看:225
本文介绍了ContinueWith(委托的CancellationToken)与等待延续等效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这种情况:

private Task LongRunningTask = /* Something */;

private void DoSomethingMore(Task previousTask) { }

public Task IndependentlyCancelableSuccessorTask(CancellationToken cancellationToken)
{
    return LongRunningTask.ContinueWith(DoSomethingMore, cancellationToken);
}

在特定的,这里吸引我的行为是 MSDN的有关延续任务页的详细在以下方面:

In particular, the behavior that interests me here is detailed in MSDN's page about Continuation Tasks in the following terms:

一个延续进入取消状态,在这些情况下:

A continuation goes into the Canceled state in these scenarios:

      
  • [...]
  •   
  • 在当前的延续是通过了<一href="http://msdn.microsoft.com/en-us/library/system.threading.cancellationtoken.aspx"><$c$c>System.Threading.CancellationToken作为参数和<一href="http://msdn.microsoft.com/en-us/library/system.threading.cancellationtoken.iscancellationrequested.aspx"><$c$c>IsCancellationRequested令牌的属性是之前的延续运行。在这样的情况下,继续维持不启动,并将其转换到<一href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskstatus.aspx"><$c$c>Canceled状态。
  •   
  • [...]
  • When the continuation was passed a System.Threading.CancellationToken as an argument and the IsCancellationRequested property of the token is true before the continuation runs. In such a case, the continuation does not start and it transitions to the Canceled state.

在code以上的作品。然而,我在把尽可能多的我延续使用等待关键字的过程。

The code above works. However, I am in the process of converting as many as possible of my continuations to using the await keyword.

有没有使用等效等待,将允许继续下去,从而被取消了期待已久的任务完成之前?

Is there an equivalent using await that would allow the continuation to be canceled before the awaited task completes?

推荐答案

下面应该这样做,尽管它看起来有点尴尬:

The following should do it, albeit it looks a bit awkward:

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

[更新] 以下svick的建议,在这里它的形状为一个帮手,根据斯蒂芬Toub的<一个href="http://blogs.msdn.com/b/pfxteam/archive/2012/08/15/implementing-then-with-await.aspx">Implementing然后等待模式:

[UPDATE] Following svick's suggestion, here it is shaped as a helper, based on Stephen Toub's Implementing Then with Await pattern:

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()是多余的,但我还没有仔细考虑过所有的边缘情况。

Perhaps, the first ThrowIfCancellationRequested() is redundant, but I haven't thoroughly considered all edge cases.

这篇关于ContinueWith(委托的CancellationToken)与等待延续等效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆