【问题标题】:What's the most efficient way to combine two Tasks?结合两个任务的最有效方法是什么?
【发布时间】:2017-07-14 22:22:17
【问题描述】:

我有两个想要按顺序运行的Task 对象。目前,我运行它们的代码如下所示:

private async Task Advance(IToken token, SyntaxKind kind)
{
    await Approach(token);
    await Surpass(token, kind);
}

我的问题是,这是组合它们的最有效方式吗?我知道async涉及很多状态机逻辑,那么使用ContinueWith会不会更高效?

private Task Advance(IToken token, SyntaxKind kind)
{
    // TODO: This would take advantage of the overload accepting a state
    // parameter to avoid the closure allocation
    return Approach(token).ContinueWith(() => Surpass(token, kind));
}

如果您认为它会更有效,请随时指出另一种方法(awaitContinueWith)。谢谢。

注意: 就我而言,我正在寻找将两个非泛型(无结果)Tasks 结合起来的最佳方式,但对于 Google 遇到这个问题的人来说,没关系包括如何在你的答案中组合两个Task<TResult>s。

【问题讨论】:

  • 您的代码已经按顺序运行ApproachSurpass。你所拥有的有什么问题?你是什​​么意思“结合他们”?
  • 您已经以两种方式编写了代码。您对“效率”的含义有了一些想法。所以:双向运行代码,双向衡量它的效率,然后你就会知道哪个“更有效”。使用科学;做一些测量。如果您不知道如何衡量“效率”,那么谁在乎哪个更有效?你说不出来。
  • 如果你关心优化而不关心保存线程之间的上下文,为什么不使用 await "await Approach(token).ConfigureAwait(false); await Surpass(token, kind).ConfigureAwait(错误的);” ?

标签: c# .net multithreading async-await task


【解决方案1】:

我的问题是,这是组合它们的最有效方式吗?我知道异步涉及很多状态机逻辑,那么使用 ContinueWith 会更高效吗?

状态机逻辑是如此微不足道,以至于在面对任何真正的异步操作(例如 I/O)时都无关紧要。确实存在一些开销,但这就是您为抽象付出的代价。我敢打赌,除非您在紧密循环中调用此方法并且大多数操作同步完成,否则开销不会很明显(甚至无法测量)。

如果“更高效”是指该方法运行速度会快几纳秒(对 CPU 来说更高效),那么是的,ContinueWithawait 更高效一点。

如果“更高效”是指代码更易于维护(对人类来说更高效),那么不,ContinueWith is much less efficient than await。它有same problems that StartNew does。您自己的示例就是一个说明:它使用当前的TaskScheduer 而不是线程池之一,并且没有使用最合适的标志。

如果您想深入了解await 的性能方面,我建议您观看Zen of Async 并阅读Understanding the Costs of Async and Await。但是,我必须提醒所有读者不要以牺牲可维护代码为代价陷入微优化。

【讨论】:

    【解决方案2】:

    一种优化执行的方法是指定TaskContinuationOptions.ExecuteSynchronously。这将导致继续在导致先前任务转换到其最终状态的同一线程上同步执行。因此,您可以避免与将延续排队到任务调度程序并由工作线程检索相关的开销。

    private Task Advance(IToken token, SyntaxKind kind)
    {
        // TODO: This would take advantage of the overload accepting a state
        // parameter to avoid the closure allocation
        return Approach(token).ContinueWith(() => Surpass(token, kind), TaskContinuationOptions.ExecuteSynchronously);
    }
    

    如果您想知道为什么默认情况下不这样做,请参阅Why is TaskContinuationsOptions.ExecuteSynchronously opt-in?

    【讨论】:

    • ExecuteSynchronously 保证任何事情。这只是对调度程序的请求。
    • @TanveerBadar: ...在绝大多数情况下都受到尊重。
    猜你喜欢
    • 2011-01-28
    • 2010-09-07
    • 2010-09-28
    • 1970-01-01
    • 2021-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多