【问题标题】:Awaiting last method call等待最后一个方法调用
【发布时间】:2015-06-13 12:41:47
【问题描述】:

一些关于堆栈溢出的帖子提出了以下建议:

任何有一个等待表达式等待任务或任务的异步方法,就在方法的末尾没有进一步处理,最好不使用异步/等待来编写。

Architecture for async/await

Await or Return

此建议是否仅适用于特定情况?在 Web 服务器上,使用 async/await 不是主要原因之一,因为在等待下面的 UpdateDataAsync 方法时,Thread 将返回到 ThreadPool,允许服务器继续工作其他要求?

鉴于这是方法中的最后一次调用,SaveDataAsync 是否应该等待数据库更新调用?

public async Task WorkWithDataAsync(Data data)
{
    ManipulateData(data);
    await SaveDataAsync(data);
    await SendDataSomewhereAsync(data);
}

public async Task SaveDataAsync(Data data)
{
    FixData(data);
    await DBConnection.UpdateDataAsync(data);
}

另外,鉴于您不知道将在哪里使用 SaveDataAsync,使其同步会损害像 WorkWithDataAsync 这样的方法,不是吗?

【问题讨论】:

    标签: c# .net asynchronous async-await


    【解决方案1】:

    删除await 并仅返回Task 不会使方法同步await 是一种工具,可以更轻松地使方法异步。这不是使方法异步的唯一方法。它的存在是因为它允许您比没有它更轻松地向任务添加延续,但是在您展示的方法中实际上您并没有利用 await 关键字来完成任何事情因此,您可以删除它并让代码简单地发挥相同的作用。

    (请注意,从技术上讲,通过删除 async 会稍微改变异常的语义;如果对您很重要,抛出的异常将从方法中抛出,而不是包含在返回的 Task 中。调用者担心,这是唯一可观察到的差异。)

    【讨论】:

    • 我明白了。所以本质上,fire and forget 方法实际上不需要标记为await,因为没有任何东西立即依赖它们的完成?
    • 这不是一种即发即弃的方法,因为它返回一个Task。但是,是的,因为从您正在编写的方法返回的任务和从您正在调用的方法返回的Task 应该同时完成,结果相同,您不妨只返回该任务,而不是而不是创建一个新任务来包装它,它只会传播相同的值。如果您在继续该任务的过程中做了比“什么都不做”更有趣的事情,await 可能会增加价值。
    【解决方案2】:

    在没有 async-await 关键字的情况下编写这些方法不会使它们同步。

    这个想法是直接返回任务,而不是产生生成状态机的开销。

    实际的区别在于异常处理。异步方法将异常封装在返回的任务中,而简单的任务返回方法则没有。

    例如,如果 FixData 抛出异常,它将在异步方法中捕获,但直接在返回一个简单任务中抛出。这两个选项将同样是异步的。

    【讨论】:

      猜你喜欢
      • 2012-05-02
      • 2013-12-15
      • 1970-01-01
      • 1970-01-01
      • 2021-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多