任务(异步,等待):我需要输入这些都是连接层还是仅具有 ASYNC 调用的层,即 HttpClient.GetAsync?
Posted
技术标签:
【中文标题】任务(异步,等待):我需要输入这些都是连接层还是仅具有 ASYNC 调用的层,即 HttpClient.GetAsync?【英文标题】:Task(async, await): Do I need to enter these are all connecting layers or only ones with ASYNC calls i.e HttpClient.GetAsync? 【发布时间】:2013-09-19 14:13:29 【问题描述】:我遇到了一个小问题,我写了一个asp.net web api服务,我在控制器上自动添加了“async”,当然这现在需要我使用await。
我遇到的问题是我的控制器连接到服务层,然后该服务层连接到数据层-该数据层是调用 GET 的 ASYNC 版本以对另一个 REST 进行异步调用的层服务 - 所以这很简单,我可以将我的数据层方法转换为具有“异步”关键字,然后我将等待 HttpClient GetSync 调用。
但是我的服务层支持 async / await 我需要将返回类型更改为 Task 但服务层实际上并没有做任何 ASYNC 它对实际调用 HttpClient 异步方法的数据层的调用。
所以考虑到我有以下层结构,我有 2 个选项。
ASP.NET Web API >> 服务层 >> 数据层
仅在数据层中使用 async 和 await 并完成它。
或者在控制器和服务层的方法上放置异步和等待,这需要重构,因为我需要返回任务。
我想在我不完全理解的地方,从技术上讲,唯一的阻塞调用将在数据层中,因此为了让所有线程返回线程池以供使用,我应该只关心在数据层上放置 async 和 await ?
我什么时候需要在控制器上使用模式???
期待任何帮助
【问题讨论】:
【参考方案1】:我在控制器上自动添加了“异步”,当然这现在需要我使用等待。
那是倒退。如果需要使用await
,则只应将async
添加到方法中。
仅在数据层中使用 async 和 await 并完成它。
You shouldn't wrap asynchronous methods within synchronous APIs。 尤其是在服务器代码中更是如此,因为这样你就失去了async
的所有好处。
或者在控制器和服务层的方法上放置异步和等待,这需要重构,因为我需要返回任务。
这是正确的方法。请遵循以下准则:
-
不要阻止
async
代码。例如,请勿致电 Task.Wait
或 Task<T>.Result
。我在我的博客how this can cause deadlocks 上进行了描述,但即使您破解它以使其可靠地工作,您仍然会失去async
在服务器端的所有好处。
避免async void
。尤其是在服务器端。
请使用await
,而不是Wait
或Result
。这意味着等待方法必须是async Task
或async Task<T>
,这意味着调用等待方法的方法也必须等待。所以async
将通过你的代码“成长”。这是正常且正确的。
您可能会发现我在 Best Practices in Asynchronous Programming 上的文章很有帮助。
【讨论】:
感谢 Stephen 的回复,是的,我明白不阻止任何 ASYNC 即。不使用 Result.... 我想你已经回答了我的问题,所以我将重构所有调用我的数据层的方法以使用 TaskWait
或Result
之类的东西,这会阻塞请求线程。
是的...太好了...好的,我正在向链中的所有方法添加异步和等待...感谢您的帮助【参考方案2】:
如果您的调用线程没有任何有意义的事情要做,那么创建一个单独的任务来为您完成工作没有任何好处。
但是,如果调用线程有其他事情要做,例如保持 UI 响应,那么调用线程可能希望在单独的任务中调用您的函数,做其他事情,当它需要结果时等待结果.
例子:
private async YourAsyncWebFunction(...)
// do some processing
// call other async functions ans wait for it to finish:
await OtherAsync(...);
var result = await OtherAsync2(...)
if (result == ...) ...
private void MyMainFunction(...)
var taskWebFunction = Task.Run( () => YourAsyncWebFunction(...));
// do other things
// after a while: you need the task to finish:
await taskWebFunction;
// do other things
如果您的主函数是事件处理程序,您不必执行 Task.Run,只需将事件处理程序声明为异步
事件处理程序是唯一可能返回 void 而不是 Task 或 Task
的异步函数<TResult
>
private async void OnButton1_Clicked(object sender, ...)
// do some processing
await YourAsyncWebFunction(...)
【讨论】:
以上是关于任务(异步,等待):我需要输入这些都是连接层还是仅具有 ASYNC 调用的层,即 HttpClient.GetAsync?的主要内容,如果未能解决你的问题,请参考以下文章