与等待继续的ContinueWith(delegate,CancellationToken)的等效

Jea*_*nal 11 .net c# async-await

我有这种情况:

private Task LongRunningTask = /* Something */;

private void DoSomethingMore(Task previousTask) { }

public Task IndependentlyCancelableSuccessorTask(CancellationToken cancellationToken)
{
    return LongRunningTask.ContinueWith(DoSomethingMore, cancellationToken);
}
Run Code Online (Sandbox Code Playgroud)

特别是,我在这里感兴趣的行为在MSDN的关于Continuation Tasks的页面中详细说明如下:

Canceled在这些场景中,延续进入状态:

上面的代码有效.但是,我正在尽可能多地使用await关键字转换我的延续.

是否存在等效使用await,允许在等待任务完成之前取消继续?

nos*_*tio 6

以下应该这样做,虽然看起来有点尴尬:

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();
}
Run Code Online (Sandbox Code Playgroud)

[更新]根据svick的建议,在这里它被塑造成一个帮手,基于Stephen Toub的实施然后与等待模式:

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 { };
}
Run Code Online (Sandbox Code Playgroud)

也许,第一个ThrowIfCancellationRequested()是多余的,但我没有彻底考虑所有边缘情况.

  • @JeanHominal,没问题.很高兴你喜欢这个概念,虽然显然我需要花费更多的迭代才能满足你所​​有的要求:)顺便说一句,我喜欢`struct Empty`和`TaskCompletionSource`,它没有受到邀请我. (2认同)