【问题标题】:How to create a cancellable task loop?如何创建可取消的任务循环?
【发布时间】:2014-03-29 18:00:37
【问题描述】:

是否可以使用 System.Threading.Task.Task 创建一个可以取消的任务循环?

流程应以 Task.Delay(x ms) 开始,然后继续执行用户定义的任务,然后是另一个 Task.Delay(y ms) 并从用户定义的任务开始重复。

var result = Task.Delay(initialDelay)
              .ContinueWith(t => dostuff..)
              .ContinueWith what goes here?

使用任务是否可行?

我可以启动一个计时器并完成它,但如果我需要取消,使用任务似乎是正确的方法,不是吗?

【问题讨论】:

    标签: c# task-parallel-library


    【解决方案1】:

    await 让这变得超级简单:

    public async Task TimedLoop(Action action, 
        CancellationToken token, TimeSpan delay)
    {
        while (true)
        {
            token.ThrowIfCancellationRequested();
            action();
            await Task.Delay(delay, token);
        }
    }
    

    没有async(但仍然只使用TPL)会有点混乱。我通常通过将 自身 附加到Task 类型的变量的延续来解决这个问题。这可以正常工作,但可能需要一秒钟才能将您的头包裹起来。如果没有await,则改用Timer 可能会更容易。

    public Task TimedLoop(Action action,
        CancellationToken token, TimeSpan delay)
    {
        //You can omit these two lines if you want the method to be void.
        var tcs = new TaskCompletionSource<bool>();
        token.Register(() => tcs.SetCanceled());
    
        Task previous = Task.FromResult(true);
        Action<Task> continuation = null;
        continuation = t =>
        {
            previous = previous.ContinueWith(t2 => action(), token)
                .ContinueWith(t2 => Task.Delay(delay, token), token)
                .Unwrap()
                .ContinueWith(t2 => previous.ContinueWith(continuation, token));
        };
        previous.ContinueWith(continuation, token);
        return tcs.Task;
    }
    

    【讨论】:

    • 我还将取消令牌传递给 Delay 方法。
    • 似乎是滥用迭代器来模拟异步的好用例。有一个图书馆。
    • @usr,关于滥用yield 的有趣想法。那个图书馆叫什么名字?
    • @Noseratio 多个人已经破解了这个想法:google.com/… 我也私下实现了这样的事情。
    • @usr,很好地使用了ContinueWith/Unwrap,尽管.NET 4.0 中没有Task.FromResult。最接近的可能是TaskCompletionSource 和即时SetResult。
    猜你喜欢
    • 2014-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多