首页 新闻 会员 周边

C# StreamWriter的异步方法效率没同步方法高

0
悬赏园豆:20 [已解决问题] 解决于 2018-01-22 23:14
private static StreamWriter _writer = new StreamWriter("test.txt", true, Encoding.Default) { AutoFlush = true };
        private async void Form1_Load(object sender, EventArgs e)
        {
            for (int i = 0; i < 10000; i++)
            {
                await _writer.WriteLineAsync(i.ToString());
            }

            for (int i = 0; i < 10000; i++)
            {
                _writer.WriteLine(i);
            }
        }

这一段代码执行,观察文件的大小发现异步方法非常慢,感觉是一个个在写出,但是同步方法却很快,一下就写完,感觉是有缓冲区一样,请问为什么会造成这个结果呢?

梦里的畅泳的主页 梦里的畅泳 | 初学一级 | 园豆:159
提问于:2018-01-22 20:01
< >
分享
最佳答案
0

你是io操作啊,而且针对同一个writer对象,就好像一堆人挤着走独木桥能快么?

异步只是提高了资源使用率,增加了吞吐而已,原来执行线程会慢慢的耗着等着db写入完成或者其他操作,用了异步后让线程这样打酱油的机会就少了

收获园豆:10
Daniel Cai | 专家六级 |园豆:10424 | 2018-01-22 22:27

  感谢解答,我懂了

梦里的畅泳 | 园豆:159 (初学一级) | 2018-01-22 22:54
其他回答(3)
0

异步本来就比同步慢的,有啥大惊小怪的。

爱编程的大叔 | 园豆:30839 (高人七级) | 2018-01-22 20:08

  异步比同步慢啊?那我是不是可以这样理解,在密集型程序中选择同步是更好的选择?异步适合控制让程序更加有灵活性?

支持(0) 反对(0) 梦里的畅泳 | 园豆:159 (初学一级) | 2018-01-22 22:02
0

这就体现了上下切换的开销,循环1万次就要进行1万次上下文切换。
异步提高效率体现在2个地方:

  • 在IO等待操作时释放线程,提高了线程的利用率,在一定并发的情况下提高了系统的吞吐量。
  • 并行操作
收获园豆:10
dudu | 园豆:30994 (高人七级) | 2018-01-22 21:57
Parallel.For(0, 10000, async i => { await _writer.WriteLineAsync(i.ToString()); });

感觉也是一样的啊

支持(0) 反对(0) 梦里的畅泳 | 园豆:159 (初学一级) | 2018-01-22 22:04

@梦里的畅泳: 这个实际并没并行,写文件的操作并行不了。而且对于文件操作,异步并不能发挥作用,System.IO.File中的文件操作并没有异步方法

支持(0) 反对(0) dudu | 园豆:30994 (高人七级) | 2018-01-22 22:28

在.net core控制台程序中测试,上面的异步操作耗时25090ms左右,同步操作只需52ms,相差500倍左右

支持(0) 反对(0) dudu | 园豆:30994 (高人七级) | 2018-01-22 22:35

@dudu: 对的,我就是很疑惑。StreamWrite中提供的异步方法我有点搞不懂

支持(1) 反对(0) 梦里的畅泳 | 园豆:159 (初学一级) | 2018-01-22 22:53

@梦里的畅泳: 如果是网络操作,StreamWrite的异步方法就有用武之地了

支持(0) 反对(0) dudu | 园豆:30994 (高人七级) | 2018-01-22 22:56

@dudu: 我现在用的就是HTTPCLIENT,但是感觉在密集型的应用中,httpclient效率反而没有httpwebrequest高

支持(0) 反对(0) 梦里的畅泳 | 园豆:159 (初学一级) | 2018-01-22 22:59

@梦里的畅泳: 确保你使用的方式是正确的,HttpClient本身是线程安全的,所以要用尽量少的实例,比如说作为静态变量里面,每次都用这个静态的实例发出请求,而不是每次请求都new一个HttpClient [这点我觉得确实是API设计的不好,也遭到了很多人的吐槽,但是既然现在是这样的,只能先这么用了]

支持(0) 反对(0) ~洛书~ | 园豆:333 (菜鸟二级) | 2018-01-23 11:01

哦,又想起一件事儿,如果是run在windows下的话,记得初始化Client的时候指定不要使用代理
new HttpClient(new HttpClientHandler{UseProxy:false})

【手打代码,领会意思即可】

支持(0) 反对(0) ~洛书~ | 园豆:333 (菜鸟二级) | 2018-01-23 11:35

@rinsen: 没有用代理的,ServerPorintManager中的连接数也设置了,但是确实没同步+线程快,在密集型应用中

支持(0) 反对(0) 梦里的畅泳 | 园豆:159 (初学一级) | 2018-01-23 14:46
0

谁说异步就一定能加快执行效率?异步如果一定能加快执行效率那还要同步的API干嘛,只要异步API就够了嘛。

异步有其适应情况,记得MS给出的标准是【来源已不可查】预期超过1ms的API才使用异步。你这个用例每次都开启一个Task,而操作只是写了个字符到流中。。。得不偿失啊。

~洛书~ | 园豆:333 (菜鸟二级) | 2018-01-23 10:55
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册