【问题标题】:C# multiple async tasks and where to properly await them when they use each other to complete?C# 多个异步任务以及当它们相互使用完成时在哪里正确等待它们?
【发布时间】:2020-09-28 14:35:20
【问题描述】:

我有两种相似的方法,但是,在对此进行理论分析之后,我很确定它们在执行上是不同的。

方法一:

        var renderDocumentDirective = await 
        RenderDocumentBuilder.Instance.GetRenderDocumentDirectiveAsync(previousPage, session);

        return await ResponseClient.Instance.BuildAlexaResponse(new Response()
        {
            shouldEndSession = null,
            directives = new List<IDirective>()
            {
                renderDocumentDirective
            }

        }, session.alexaSessionDisplayType);

方法二

            var renderDocumentDirective = RenderDocumentBuilder.Instance.GetRenderDocumentDirectiveAsync(previousPage, session);
            return await ResponseClient.Instance.BuildAlexaResponse(new Response()
            {
                shouldEndSession = null,
                directives = new List<IDirective>()
                {
                    await renderDocumentDirective
                }

            }, session.alexaSessionDisplayType);

第一种方法在异步任务RenderDocumentBuilder 上使用await 运算符,然后在ResponseClient 中使用它,这也是一个异步任务。

然而,第二种方法设置了任务RenderDocumentBuilder,但直到它位于 ResponseClient 内部时才调用等待的方法,此时它正在等待返回数据。

执行此方法的两种方式都有效,但我不清楚它是否适合:

  • 等待 ResponseClient 之外的任务? (方法一)

  • 或者,在 ResponseClient 之外创建 renderDocumentDirective 任​​务并在方法内等待它是否合适? (方法二)

【问题讨论】:

  • 我认为第一个更清晰易读,但除非new Response() 调用有一些奇怪的副作用,否则它们几乎相同。
  • 看看他们编译成什么 IL 会很有趣;我怀疑同样的事情。我会呼应 Guru Stron,因为第一个更具可读性并且意图更清晰。另外,我认为您可以更好地处理第一个示例中GetRenderDocumentDirectiveAsync 引起的任何异常。
  • @GuruStron 为什么ResponseClient.Instance 的实现很重要?在等待之前评估整个表达式。
  • @JohnathanBarclay 是的,同意。
  • 你的意思是在等待之前评估它,因为它是一个单例实例吗?

标签: c# async-await


【解决方案1】:

我认为您误解了数据流。

这是你的两个方法,写得更详细一些

方法一

var renderTask = RenderDocumentBuilder.Instance.GetRenderDocumentDirectiveAsync(previousPage, session);

var renderDocumentDirective = await renderTask;

var alexaResponse = new Response();

alexaResponse.shouldEndSession = null,
alexaResponse.directives = new List<IDirective>();
alexaResponse.directives.Add(renderDocumentDirective);

var buildTask = ResponseClient.Instance.BuildAlexaResponse(alexaResponse, session.alexaSessionDisplayType);

return await buildTask;

方法二

var renderTask = RenderDocumentBuilder.Instance.GetRenderDocumentDirectiveAsync(previousPage, session);

var alexaResponse = new Response()
alexaResponse.shouldEndSession = null,
alexaResponse.directives = new List<IDirective>();
alexaResponse.directives.Add(await renderTask);

var buildTask = ResponseClient.Instance.BuildAlexaResponse(alexaResponse, session.alexaSessionDisplayType);

return await buildTask;

所以你看到唯一真正的区别是方法 2 创建 Response 对象,设置 shouldEndSession 并在之前创建 List 对象,或者它等待 renderTask

方法 2 可能是有益的,但这取决于GetRenderDocumentDirectiveAsync 的实现方式(即真正的异步)。但即使是这样,方法 2 也不太可能带来任何性能提升,因为这两种方法之间没有太大区别。

也就是说,我会使用方法 1,因为它看起来更像同步代码,并且在大多数情况下,您希望在任务可用时立即等待它,因为 await/async 主要是关于释放线程来做其他事情而不是平行性。

【讨论】:

    猜你喜欢
    • 2014-09-20
    • 2021-05-11
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多