【问题标题】:Should I use async if I'm returning a Task and not awaiting anything如果我要返回一个任务并且不等待任何东西,我应该使用异步吗
【发布时间】:2017-05-28 07:51:15
【问题描述】:

在代码不是awaiting 任何东西的异步方法中,是否有人将其标记为异步,等待任务,然后返回?

除了潜在的不必要之外,这样做的负面影响是什么?

对于这个例子,请假设QueryAsync<int> 返回Task<int>

private static async Task<int> InsertRecord_AsyncKeyword(SqlConnection openConnection)
{
    int autoIncrementedReferralId =
        await openConnection.QueryAsync<int>(@"
            INSERT INTO...
            SELECT CAST(SCOPE_IDENTITY() AS int)"
    );

    return autoIncrementedReferralId;
}

private static Task<int> InsertRecord_NoAsyncKeyword(SqlConnection openConnection)
{
    Task<int> task =
        openConnection.QueryAsync<int>(@"
            INSERT INTO...
            SELECT CAST(SCOPE_IDENTITY() AS int)"
    );

    return task;
}

// Top level method
using (SqlConnection connection = await DbConnectionFactory.GetOpenConsumerAppSqlConnectionAsync())
{
    int result1 = await InsertRecord_NoAsyncKeyword(connection);
    int result2 = await InsertRecord_AsyncKeyword(connection);
}

【问题讨论】:

  • 使用async 的方法从调用者的角度来看并不相同。两者都是返回Task 的方法。 async 关键字只是使您可以在方法内部使用await,而不是调用者。
  • @NiyokoYuliawan 我很好奇提前等待是否会对性能产生任何影响。
  • 也就是说 - 假设您信任代码的用户正确使用该方法 - 不,我看不到任何好处。
  • @Rob 它将在两个版本中并行运行(假设 QueryAsync 确实是异步的)。 await 对启动 Task 没有影响(因为代码的同步部分在两种情况下运行相同)。

标签: c# asynchronous async-await


【解决方案1】:

阅读来自Stephen Cleary的这篇博文:

Eliding Async and Await

【讨论】:

    【解决方案2】:

    不,您不应该只在没有await 的方法中添加async - 甚至会有编译器警告。

    您也不应该在此类方法中不必要地添加await,因为它会使编译器为该方法生成明显更复杂的代码,并具有一些相关的性能影响。

    从时间的角度来看,两种模式之间没有明显的区别 - 任务仍将异步运行,您仍然可以立即等待或稍后在调用者中等待。

    我能想到一个区别——如果你直接返回任务,调用者可以使用ConfigureAwait(false),它会在其他线程上完成。当您 await 内部的该任务时,该方法控制 await 之后的代码在何处执行。

    请注意,最后使用单个 await 的方法的成本并不比没有的方法成本低得多 - 因此,如果您更喜欢编码风格,在所有异步方法上一致使用 async,除了很少的时间关键部分外,它可能很好.

    【讨论】:

    • 添加asyncawait 的另一个有用案例是用try 块包装您的代码。尽管 try 块在这两种情况下都可以编译,但行为却大不相同。
    • @Aron 在特定情况和错误捕获中是有意义的。对于我给出的插入示例,我可能会尝试在调用堆栈的更高位置。
    • @contactmatt 我不同意。我同意实际的错误“处理”应该在堆栈中进一步完成。但是,这是丰富异常的正确位置。在您的情况下,我会捕获 SqlException 并重新抛出具有更多应用程序特定异常的异常。
    • 一个区别:如果它不等待它,如果下游异步方法抛出异常(即如果任务失败)返回任务的方法将不会出现在异步调用堆栈中
    猜你喜欢
    • 1970-01-01
    • 2017-08-23
    • 2018-11-27
    • 2014-10-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-12
    • 2018-10-12
    相关资源
    最近更新 更多