始终使用“异步”,并在库异步方法'等待'关键字? [英] Always use the 'async' and 'await' keywords in asynchronous methods in a library?

查看:307
本文介绍了始终使用“异步”,并在库异步方法'等待'关键字?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

摘要:在库的方法,我应该使用异步的await 关键字而不是返回工作直接?

我相信我的问题是有关<一个href=\"http://stackoverflow.com/questions/22063721/should-i-wrap-a-task-in-another-task-or-should-i-just-return-the-created-task\">this 之一。然而,问题是关于 .NET 4.0 和TPL,而我使用.NET 4.6的异步等待关键字。所以,我想是因为当链接问题得到回答不存在这些关键字,我的问题可能会得到不同的答案。

说明:我在写一个外部WCF服务的一个简单的包装和包装,使多个 SendAsync 来电。现在我认为,每个包装方法应该只返回一个任务&LT;&GT; 的情况下直接被期待已久的。我的理解是,异步 / 伺机应在应用层上使用,而且的的库中。

因此​​,举例来说,这里要说的是,我想我应该为每个包装方法的办法:

 私人任务&LT; SignResponse&GT; GetSignDataAsync(SigningRequestType要求)
{
    返回_service.SendAsync(请求);
}

但在互联网上,我发现的几个职位使用这种方法来代替:

 专用异步任务&LT; SignResponse&GT; GetSignDataAsync(SigningRequestType要求)
{
    返回等待_service.SendAsync(要求).ConfigureAwait(假);
}

这是另外一个例子,我发现<一个href=\"http://social.technet.microsoft.com/wiki/contents/articles/21177.visual-c-thread-sleep-vs-task-delay.aspx\"相对=nofollow> TechNet上:

 异步任务PutTaskDelay()
{
    等待Task.Delay(5000);
}私人异步无效btnTaskDelay_Click(对象发件人,EventArgs的发送)
{
    等待PutTaskDelay();
    的MessageBox.show(我回来了);
}

所以,当我应该使用第二种方法(即包含一个异步等待关键字)?为什么不直接返回一个整体工作未做 PutTaskDelay 异步 ?我想我应该回到工作直接每当它是可能的,并使用异步 / 等待来得到仅在应用层的最终结果。我对吗?如果不是,那我在这里展示的两种方法之间的区别是什么呢?

我的关心:当异步等待使用关键字,似乎它只是提供了额外的工作,编译器没有任何好处。


解决方案

  

我应该使用异步库等待?


这一切都依赖。如果你打算采取异步编程范式的优势,那么答案是是的异步的await 需要使用关键字的的大部分时间的。更可能的,你会发现自己需要使用异步/的await 。这是因为在大多数情况下,这将是很难只用工作任务&LT; T&GT; ,你将超过可能需要推理,你调用异步操作的结果。

此外,根据您的问题,它好像你可能对关键字本身有些混乱,他们如何与工作任务&LT ; T&GT; 类型。请允许我澄清这个给你。

异步 <参数 / A>关键字允许的方法来使用 的await 关键字。最好的做法是让所有异步方法返回为任务任务&LT; T&GT; 除非您无法(例如,当你上面展示了一个按钮单击事件处理)。

返回方法工作任务&LT; T&GT; 重新present异步操作。当你在一个库,建议总是使用 .ConfigureAwait(假)的详细原因的此处。此外,我总是指向人关于这个问题这方面的详细文章

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

下面的方法返回一个任务&LT; SignResponse&GT; 。这是一个异步的操作,重新presents工作签到。该方法可以被调用者期待获得 SignResponse

 私人任务&LT; SignResponse&GT; GetSignDataAsync(SigningRequestType要求)
{
    返回_service.SignAsync(请求);
}

同样,这个版本做同样的事...的除了异步/的await 不需要关键字​​的。不需要他们的原因是,该方法本身并不需要使用 SignResponse ,因此它可以简单的返回任务&LT; SignResponse&GT; 如上所示。而当你在你的问题指出,的确有罚款,当你使用异步/的await 时是不需要的关键词。这样做增加了额外的状态机步骤,因为其结果是产生了,因为它的期待已久的。

 专用异步任务&LT; SignResponse&GT; GetSignDataAsync(SigningRequestType要求)
{
    返回等待_service.SignAsync(要求).ConfigureAwait(假);
}

最后,如果你需要推理的反应,可以使用前面提到的关键字,这样做是这样的:

 专用异步任务&LT; SignResponse&GT; GetSignDataAsync(SigningRequestType要求)
{
    VAR的结果=等待_service.SignAsync(要求).ConfigureAwait(假);
    如果(result.SomeProperty == SomethingWeCareToCheck)
    {
        _log.Log(哇,这是未预期的...);
    }
    返回结果;
}

Summary: In a library method, when should I use the async and await keywords instead of returning a Task 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 the async and await 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 a Task<> directly without being awaited. My understanding is that async/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 and await keywords)? Why not just return a whole Task without making PutTaskDelay async? I think that I should return Task directly whenever it is possible, and use async/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 and await 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 and await keywords are needed most of the time. More than likely, you will find yourself needing to use async/await. That is because in most situations it would be difficult to use only Task and Task<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 and Task<T> types. Allow me to clarify this for you.

The async keyword allows a method to use the await keyword. The best practice is to have all async methods return either Task or Task<T> unless you are unable to (for example, a button click event handler as you demonstrated above).

Methods that return Task or Task<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 get SignResponse.

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 use SignResponse and therefore it could simply return Task<SignResponse> as shown above. And as you indicated in your question, there is indeed a penalty when you use the async/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;
}

这篇关于始终使用“异步”,并在库异步方法'等待'关键字?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆