本文翻译自《Should I expose asynchronous wrappers for synchronous methods? - Stephen Toub》,原文地址:Should I expose asynchronous wrappers for synchronous methods?(microsoft.com)
注:我会对照原文进行逐句翻译,但是考虑到中西方表达方式以及中英文语法的差异,我会适当的修改语句的顺序和陈述方式。此外,限于自身英文和技术水平,有些词或者句子的翻译并不能表达原文的意思,对于这些词语我会同时标注原文用词。个人水平有限,有不对的地方请多批评指教。文章中会添加我自己对原文的一些理解,有不对的地方也请多批评指教。
注:我就这么干过。那是否推荐这种做法呢?作者 Stephen Toub 说:别这样er
以下内容是我自己加的,仅供娱乐,有不对的地方请指教批评。
关于 scalability 和 offloading:不太知道应该怎么翻译,查阅了英文释义也没能准确地表达出来,我做的了解如下:
关于 technical computing 和 agent-based simulation workload:我不太明白这两个词所对应的工作领域,目前理解就是有大量计算的工作。
- 可扩展性(scalability):指应用程序处理增加的工作量的能力。比如用一台服务器能满足一些要求,当添加了第二台服务器之后,完成同样的工作只需要一半的时间,或者说每分钟可以处理原来两倍数量的工作,那就表示应用的可扩展性强。可以参考 What does "scalability" mean? - Stack Overflow 和 What Is Scalability?, by Chris Shiflett。
- 负载转移(offloading):把工作转移到其它资源进行处理。可以参考 Computation offloading - Wikipedia。
以下内容是我自己加的,仅供娱乐,有不对的地方请指教批评。举个例子,有一个同步方法 Sleep(),该方法在 N 毫秒后才会结束执行:
真正的异步操作是很难自己去实现的,.NET 库中提供的异步方法都是使用”标准P/Invoke异步I/O系统“实现的,这种真正的异步操作不会有其它线程的参与。所以自己基于.NET中提供的同步方法包装的异步方法是不会有助于可扩展性的。可以参考 Stephen Cleary 的文章:There Is No Thread (stephencleary.com),这篇文章后续可能会进行翻译,方便自己快速回顾。
以下内容是我自己加的,仅供参考,有不对的地方请指教批评。
第一中方式没有减少资源消耗,只是把阻塞的线程从调用它的线程转到了线程池中的另一个线程,这对扩展性来说没有提升,但它确实可以避免阻塞调用它的线程,这对 UI 应用来说是有用的,但是在异步代码中一般会使用 Task.Delay() 而不是 Thread.Sleep()。两者的区别可以参考: c# - When to use Task.Delay, when to use Thread.Sleep? - Stack Overflow。
第二种方式使用了 Timer 来实现相同的操作,文章中提到这可以消耗更少的资源,原因是这种方法仅依赖于一个计时器的回调。其实 Timer 也是使用了线程池中的线程,只不过所有的 Timer 实例只会使用同一个线程,而且 Task.Delay 方法内部也使用了 Timer,可以查看源码:runtime/Task.cs at main · dotnet/runtime (github.com)。
以下内容是我自己加的,仅供参考,有不对的地方请指教批评。
这部分没有太明白,翻译也就会不准确,建议可以阅读原文。我大概理解就是通过异步调用把某部分代码和异步方法外的执行环境分隔开。
以下内容是我自己加的,仅供参考,有不对的地方请指教批评。例如,Dictionary.Add(TKey,TValue),这是一个非常快速的方法,但请记住 Dictonary 类是如何工作的:它需要对 Key 进行哈希处理才能找到正确的用来保存它的 bucket,并且它需要检查该 Key 与 bucket 中已存在的其他项是否相等。这一系列哈希处理和相等性检查可能会导致调用用户代码,而这些操作具体做什么或需要多长时间是不知道的。那 Dictionary 类上的每个方法都应该公开一个异步包装器吗?这显然是一个极端的例子,但也有简单点儿的例子,比如 Regex,提供给 Regex 的正则表达式模式的复杂性以及输入字符串的性质和大小可能会对 Regex 匹配的运行时间产生较大影响,以至于 Regex 现在支持可选超时。Regex 上的每个方法都应该有等价的异步方法吗?我真的希望不会那样。
基于同步的异步方法:
这句话的原文是 “async over sync”,按照我的理解这句话是指那些使用 Task.Run 这种方法把原有的同步方法包装成为的异步方法。或者也可以翻译成”同步之上的异步“,大概意思就是这样吧。
以下内容是我自己加的,仅供参考,有不对的地方请指教批评。
听君一席话,如听一席话。
读完整篇文章之后,可能会觉得好像看半天,但好像又没有学到什么。不过我还是想说一下我自己从这篇文章看到的东西。
在我们使用异步的时候,首先要想清楚使用异步的目的是什么。如果只是因为微软推荐使用异步或者大家都说异步好,所以就把原有的同步方法或者准备创建的新的同步方法通过 Task.Run 改成异步方法,那这样的想法是错误的。因为文章中已经提到,如果是为了提升性能而这么做的话是没有意义的,它不会提升程序性能,反而可能会引起性能问题。但是如果是为了实现类似不阻塞 Winform 主线程的效果的话也是可以这么做的。
原文的标题是 Should I expose asynchronous wrappers for synchronous methods,是指如果我们写的代码是需要提供给其他人使用的,是否应该对外公开这种假异步方法。当然读完文章后我们自然明白这种做法是不应该的。
其次,当我们想好使用异步的目的后,就要考虑如何实现异步了。文章中提到自己实现一个真正的异步是很难的,所以在自己编写 .NET 没有提供的异步方法时就要慎重了。
最后,我翻译文章主要是为了方便自己以后能快速回顾(毕竟看英文需要在脑子中先翻译成中文才能开始消化),另外把自己看到的内容输出出去也是一种吸收。英文和技术水平都有限,有不对的地方请指教批评,感谢!
欢迎光临 IT评测·应用市场-qidao123.com技术社区 (https://dis.qidao123.com/) | Powered by Discuz! X3.4 |