如果我要返回一个任务并且不等待任何东西,我应该使用异步吗

Posted

技术标签:

【中文标题】如果我要返回一个任务并且不等待任何东西,我应该使用异步吗【英文标题】: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);

【问题讨论】:

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

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

Eliding Async and Await

【讨论】:

【参考方案2】:

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

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

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

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

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

【讨论】:

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

以上是关于如果我要返回一个任务并且不等待任何东西,我应该使用异步吗的主要内容,如果未能解决你的问题,请参考以下文章

广播接收器未被呼叫

Celery:当排队太多时阻止添加更多任务

PyQt ProgressBar

SQL存储过程等待并按顺序执行

图像模糊的简单指标?

什么是 C++ 11 触发异步任务并忘记它的方法?