网站布局优化,十大微信小程序游戏,wordpress加个微信登录,河北省建设部网站微信公众号#xff1a;架构师高级俱乐部关注可了解更多的编程#xff0c;架构知识。问题或建议#xff0c;请公众号留言;如果你觉得此文对你有帮助#xff0c;欢迎转发在.NET中执行异步/等待的两种错误方法 在应用开发中#xff0c;我们为了提高应用程序的吞吐能力或者异步… 微信公众号架构师高级俱乐部关注可了解更多的编程架构知识。问题或建议请公众号留言;如果你觉得此文对你有帮助欢迎转发在.NET中执行异步/等待的两种错误方法 在应用开发中我们为了提高应用程序的吞吐能力或者异步操作来减少耗时通常会使用多线程来达到目的而在C#语言中由于async/await必杀技的存在大多会使用此来简化多线程操作async/await的具体使用方式想必大家已烂熟于心不再赘述今天主要谈谈在我们经常所谓的async/await操作真的是正确的吗你又真的用对他了吗情景1消除异步方法优势 请看下面代码示例ServiceClient client new ServiceClient();
ServiceRequest request new ServiceRequest();
request.Id newId;
var responseTask Task.Run(() client.GetServicesAsync(request));
ServiceResponse response await responseTask;以上代码片段在一个异步方法中此方法在另一个Task中返回一个Task(Task.Run) 这是多余的。如果该方法已经返回Task则我们不应该将其包装在另一个Task中。因此在这种情况下解决方案也非常简单取消一切不必要的TaskServiceClient client new ServiceClient();
ServiceRequest request new ServiceRequest();
request.Id newId;
var responseTask client.GetServicesAsync(request);
ServiceResponse response await responseTask;情景2滥用Task.Run() 在工作中大多使用Task.Run的代码给人的印象是异步有助于提高性能。这是正确的但仅是非常片面的。Async/Await的目的是帮助提高吞吐量。改善性能仅仅是副作用。因此在工作中会发现各种奇奇怪怪的代码例如以下为了配合外部异步方法又由于内部各种原因没有实现异步方法不得不用Task.Run来包裹同步方法而达到语法要求。MyService client new MyService();
var responseTask Task.Run(() client.GetData(request));
var response await responseTask;换句话说使用Task.Run()包装了一个同步调用。这里的问题是方法client.GetData()本身并不是异步方法,通过将异步包装器置于同步方法之上我们正在做一个称为“async-over-sync异步超同步”的反模式这在大多数情况下最终不是一个推荐的做法。不是因为它不起作用而是起作用而是因为它效率不高。之所以如此原因是很长的而且涉及很多如果感兴趣可在文章末尾找到Stephen作者相关对此问题的详细解释地址[1]。总结一下以上代码非常糟糕因为实现异步的好处是通过在线程不执行任何操作例如等待服务响应时“释放”线程来提高吞吐量。上面的示例确实释放了一个线程它也立即消耗了另一个线程来执行任务包装的代码并且该消耗的线程在等待服务响应时被阻塞。因此我们没有提高吞吐量只是将工作从一个线程转移到了另一个线程。而且在并发下以上使用方式在工作中也极大的降低了系统性能解决方案可以简化为不要对同步方法使用异步包装器只需同步调用它们即可。在这种情况下理论上的性能优势将被潜在的问题所抵消这些潜在的问题在最坏的情况下可能包括死锁。过度使用Task.Run()有很大安全隐患尤其在你未搞懂你写了什么的时候这种影响在复杂业务和超大并发下出问题非常难排查在发现性能严重影响又找不到原因的时候请排查出所有使用Task.Run的代码确定是否是以上两种情况解决他们可能就海阔天空了摘要在.NET或者.Netcore中使用Async/Await都是一项技巧必须谨慎使用。在上面的示例中开发团队试图使他们的应用程序性能更好但最终由于对他们的代码过度使用Async/Await而使情况变的难以控制。总之应该记住两件事不要将异步任务包装在另一个异步包装器Task.Run中。不要在同步调用上使用异步包装器。有很多方法可以修正使用异步/等待的ASP.NET代码。更多请参考[1]:https://devblogs.microsoft.com/pfxteam/should-i-expose-asynchronous-wrappers-for-synchronous-methods/(我应该为同步方法加异步包装器Task.Run吗)