返回一个Task而不是等待内部方法调用

时间:2017-03-10 10:45:53

标签: c# asynchronous async-await task

我看到一些同事代码,他选择不等待数据库调用,只返回任务。 E.g。

public Task<UpdateResult> AddActivityAsync(ClaimsPrincipal principal, Activity activity)
{
    return _userManager.SaveToDatabaseAsync(principal, activity);
}

因为_userManager.SaveToDatabaseAsync是异步的,我会以这种方式实现

public async Task<UpdateResult> AddActivityAsync(ClaimsPrincipal principal, 
                                                                      Activity activity)
{
    return await _userManager.SaveToDatabaseAsync(principal, activity);
}

此方法的调用方法始终等待它:

await _profile.AddActivityAsync(..., ...)

不使内部方法异步并且只返回任务,让调用者等待它有什么好处吗?我以为我们必须一直写下Async ......

2 个答案:

答案 0 :(得分:2)

这取决于具体情况。

必须等待,例如,如果要等待的代码绑定到using上下文中的对象(或手动处理):

using (SomeDisposableType obj = ...)
{
    await obj.SomeOperationAsync();
}

如果您在没有等待的情况下返回任务,那么该方法可能会抱怨该对象在完成其工作之前已被处理掉。 (并非所有的一次性物品都会抛出ObjectDisposedException,如果你试图在它们被处理后对它们进行某些操作,但通常这样做是个好主意)。考虑相反的情况:

using (SomeDisposableType obj = ...)
{
    // This returns the Task that represents the async operation,
    // and because it returns, the control goes out of the using
    // scope, and therefore obj gets disposed.
    return obj.SomeOperationAsync();
}

所以有时需要等待。如果情况并非如此,我无法想到你无法返回Task本身的原因。

答案 1 :(得分:1)

您不需要等待返回Task<T>的方法,如果您在方法上有async关键字,代码将只是异步运行。你的同事已经删除了,因此故意同步运行并让调用代码实现它,如果他们愿意的话。

这取决于运行此代码的层。如果它很深,那么让更高的代码层选择同步执行并在那里保持控制可能会更好。

你绝对不需要'一直写下异步'。 async关键字的目的只是将方法标记为能够返回Task<T>并能够使用await关键字。 await关键字调用框架来执行Task并提供异步处理。

TL; DR:这是一个选择。

我欢迎任何改进或纠正我的人,因为我不是大师。