更新时间:2022-10-30 20:03:06
我应该使用异步库等待?
块引用>这一切都依赖。如果你打算采取异步编程范式的优势,那么答案是是的
异步
和的await
需要使用关键字的的大部分时间的。更可能的,你会发现自己需要使用异步/的await
。这是因为在大多数情况下,这将是很难只用工作
和任务< T>
,你将超过可能需要推理,你调用异步操作的结果。此外,根据您的问题,它好像你可能对关键字本身有些混乱,他们如何与
工作
和任务&LT ; T>
类型。请允许我澄清这个给你。异步
/ A>关键字允许的方法来使用
的await
关键字。***的做法是让所有异步方法返回为任务
或任务< T>
的除非您无法(例如,当你上面展示了一个按钮单击事件处理)。返回方法
工作
或任务< T>
重新present异步操作。当你在一个库,建议总是使用.ConfigureAwait(假)
的详细原因的此处。此外,我总是指向人关于这个问题这方面的详细文章要区分你的问题的两种方法:
下面的方法返回一个
任务< SignResponse>
。这是一个异步的操作,重新presents工作签到。该方法可以被调用者期待获得SignResponse
。私人任务< SignResponse> GetSignDataAsync(SigningRequestType要求)
{
返回_service.SignAsync(请求);
}同样,这个版本做同样的事...的除了
异步/的await
不需要关键字的。不需要他们的原因是,该方法本身并不需要使用SignResponse
,因此它可以简单的返回任务< SignResponse>
如上所示。而当你在你的问题指出,的确有罚款,当你使用异步/的await
时是不需要的关键词。这样做增加了额外的状态机步骤,因为其结果是产生了,因为它的期待已久的。专用异步任务< SignResponse> GetSignDataAsync(SigningRequestType要求)
{
返回等待_service.SignAsync(要求).ConfigureAwait(假);
}最后,如果你需要推理的反应,可以使用前面提到的关键字,这样做是这样的:
专用异步任务< SignResponse> GetSignDataAsync(SigningRequestType要求)
{
VAR的结果=等待_service.SignAsync(要求).ConfigureAwait(假);
如果(result.SomeProperty == SomethingWeCareToCheck)
{
_log.Log(哇,这是未预期的...);
}
返回结果;
}Summary: In a library method, when should I use the
async
andawait
keywords instead of returning aTask
directly?I believe my question is related to this one. However, that question is about
.NET 4.0
and the TPL, while I'm using .NET 4.6 with theasync
andawait
keywords. So, I think my question might get different answers because these keywords didn't exist when the linked question was answered.Explanation: I'm writing a simple wrapper for an external WCF service and the wrapper makes multiple
SendAsync
calls. Now I think that each wrapper method should just return aTask<>
directly without being awaited. My understanding is thatasync
/await
should be used on the application layer, and not within a library.So, for example, here is the approach that I think I should take for each wrapper method:
private Task<SignResponse> GetSignDataAsync(SigningRequestType request) { return _service.SendAsync(request); }
But on the Internet, I found several posts that use this approach instead:
private async Task<SignResponse> GetSignDataAsync(SigningRequestType request) { return await _service.SendAsync(request).ConfigureAwait(false); }
And here is another example that I found on technet:
async Task PutTaskDelay() { await Task.Delay(5000); } private async void btnTaskDelay_Click(object sender, EventArgs e) { await PutTaskDelay(); MessageBox.Show("I am back"); }
So, when should I use the second approach (the one that includes the
async
andawait
keywords)? Why not just return a wholeTask
without makingPutTaskDelay
async
? I think that I should returnTask
directly whenever it is possible, and useasync
/await
to get a final result in the application layer only. Am I right? If not, what is the difference between the two approaches that I show here?My concern: When the
async
andawait
keywords are used, it seems that it just provides additional work to the compiler without any benefit.Should I use async await in library?
It all depends. If you're going to take advantage of the asynchronous programming paradigm, then the answer is "yes," the
async
andawait
keywords are needed most of the time. More than likely, you will find yourself needing to useasync/await
. That is because in most situations it would be difficult to use onlyTask
andTask<T>
as you will more than likely need to reason about the results of the async operations that you invoke.Additionally, based on your question it seems as though you may have some confusion about the keywords themselves and how they relate to the
Task
andTask<T>
types. Allow me to clarify this for you.The
async
keyword allows a method to use theawait
keyword. The best practice is to have all async methods return eitherTask
orTask<T>
unless you are unable to (for example, a button click event handler as you demonstrated above).Methods that return
Task
orTask<T>
represent asynchronous operations. When you are in a library it is suggested to always use.ConfigureAwait(false)
for reasons detailed here. Additionally, I always point people to this detailed article on the subject.To differentiate the two approaches in your question:
The method below returns a
Task<SignResponse>
. This is an async operation that represents the work to sign in. The method can be awaited by the caller to getSignResponse
.private Task<SignResponse> GetSignDataAsync(SigningRequestType request) { return _service.SignAsync(request); }
Likewise, this version does the same thing...except that the
async/await
keywords are not needed. The reason they are not needed is that the method itself does not need to useSignResponse
and therefore it could simply returnTask<SignResponse>
as shown above. And as you indicated in your question, there is indeed a penalty when you use theasync/await
keywords when they are not needed. Doing so adds an extra state machine step as the result is yielded, since its awaited.private async Task<SignResponse> GetSignDataAsync(SigningRequestType request) { return await _service.SignAsync(request).ConfigureAwait(false); }
Finally, if you needed to reason about the response, you could use the aforementioned keywords to do so like this:
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; }