始终在库中的异步方法中使用"async"和"await"关键字?

Ale*_*kiy 14 .net c# asynchronous async-await .net-4.6

简介:在库方法中,何时应该使用asyncawait关键字而不是Task直接返回?

我相信我的问题与问题有关.但是,这个问题是关于.NET 4.0和TPL,而我正在使用.NET 4.6 asyncawait关键字.所以,我认为我的问题可能得到不同的答案,因为在回答链接问题时这些关键字不存在.

说明:我正在为外部WCF服务编写一个简单的包装器,并且包装器会进行多次SendAsync调用.现在我认为每个包装器方法都应该直接返回Task<>,而不必等待.我的理解是async/ await应该在应用层上使用,而不是在库中.

因此,例如,我认为我应该为每个包装器方法采用的方法:

private Task<SignResponse> GetSignDataAsync(SigningRequestType request)
{
    return _service.SendAsync(request);
}
Run Code Online (Sandbox Code Playgroud)

但是在互联网上,我找到了几个使用这种方法的帖子:

private async Task<SignResponse> GetSignDataAsync(SigningRequestType request)
{
    return await _service.SendAsync(request).ConfigureAwait(false);
}
Run Code Online (Sandbox Code Playgroud)

这是我在technet上找到的另一个例子:

async Task PutTaskDelay()
{
    await Task.Delay(5000);
} 

private async void btnTaskDelay_Click(object sender, EventArgs e)
{
    await PutTaskDelay();
    MessageBox.Show("I am back");
}
Run Code Online (Sandbox Code Playgroud)

那么,我何时应该使用第二种方法(包含asyncawait关键字的方法)?为什么不在Task没有制作的情况下返回整体PutTaskDelay async?我认为我应该Task尽可能直接返回,并使用async/ await仅在应用程序层中获得最终结果.我对吗?如果没有,我在这里展示的两种方法有什么区别?

我担心:当使用asyncawait关键字时,它似乎只是为编译器提供了额外的工作而没有任何好处.

Dav*_*ine 8

我应该在库中使用async await吗?

这完全取决于.如果您要利用异步编程范例,那么答案是"是",大多数时候都需要asyncawait关键字.很可能,你会发现自己需要使用.这是因为在大多数情况下,仅使用它很困难,因为您很可能需要推断您调用的异步操作的结果.async/awaitTaskTask<T>

此外,根据您的问题,它好像你可能对关键字本身以及它们如何涉及到一些混乱TaskTask<T>类型.请允许我为您澄清一下.

async关键字允许使用的方法await关键字.最佳做法是让所有异步方法返回TaskTask<T> 除非您无法返回(例如,如上所示,按钮单击事件处理程序).

返回TaskTask<T>表示异步操作的方法.当您在图书馆时,建议您始终使用此处.ConfigureAwait(false)详述的原因.另外,我总是向人们指出关于这个主题的详细文章.

要区分问题中的两种方法:

下面的方法返回一个Task<SignResponse>.这是一个异步操作,表示要登录的工作.调用者可以等待该方法SignResponse.

private Task<SignResponse> GetSignDataAsync(SigningRequestType request)
{
    return _service.SignAsync(request);
}
Run Code Online (Sandbox Code Playgroud)

同样,这个版本做同样的事情...... 除了async/await不需要关键字.它们不需要的原因是该方法本身不需要使用SignResponse,因此它可以简单地返回Task<SignResponse>如上所示.正如您在问题中指出的那样,当您async/await不需要使用关键字时,确实存在惩罚.这样做会增加一个额外的状态机步骤,因为它等待了结果.

private async Task<SignResponse> GetSignDataAsync(SigningRequestType request)
{
    return await _service.SignAsync(request).ConfigureAwait(false);
}
Run Code Online (Sandbox Code Playgroud)

最后,如果您需要推理响应,可以使用上述关键字来执行此操作:

private async Task<SignResponse> GetSignDataAsync(SigningRequestType request)
{
    var result = await _service.SignAsync(request).ConfigureAwait(false);
    if (result.SomeProperty == SomethingWeCareToCheck)
    {
        _log.Log("Wow, this was un-expected...");
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)

  • 可能值得一提的是,[功能请求](https://github.com/dotnet/roslyn/issues/1981)让编译器变得更加智能`return await`(这是方法中唯一的等待) ). (2认同)