对于IO密集型的应用(比如数据库访问,磁盘访问,网络访问)来讲,是不需要分配一个线程的(不怎么准确,但可以这么理解),那么使用一个后台线程运行这些操作来实现异步是低效的。而实际上我们的应用中充斥着大量的IO密集型操作(除了那些做游戏应用计算密集型)。经过测试,actualRead的长度可能会比BUFFER_LENGTH 小,但这并不代表网络传输已经结束,比如我采用异步方式下载网页的时候,我定义了1024Buffer字节数组,但每次异步获取的字节长度都不足1024字节,在这种情况下不能关闭网络流的。线程间操作无效: 从不是创建控件“txtContent”的线程访问它。一般我们可以将我们的应用分为计算密集型,比如进行图像处理,解方程等,另一种就是IO密集型,比如访问数据库,访问磁盘等。
分清楚这两种了后我们再往下看。
计算密集型的代码是大量占用CPU时间,所以你用ThreadPool.QueueUserWorkItem也好,用BeginInvoke也好,都是分配一个线程来运算,无所谓(ThreadPool更佳)
IO密集型计算,我们大部分时间是在等待IO操作的,CPU并没有花多少时间来运算。所以我们不需要分配一个线程来单独进行IO,我们只需要使用异步发起IO操作,然后CPU自己干自己的事儿,当IO完成后,会回调。这样的效率就会更高。
BeginInvoke不会创建线程,你从哪里看到的?
BeginInvoke
是将操作放到另外一个线程上执行。这个线程来自线程池。

我的意思是说,对于IO操作不要将其放到另外一个线程上,这是浪费。

关于BeginInvoke是否创建线程要怎么看。
BeginInvoke调用时,CLR会将任务放到线程池的线程上执行,不是调用方法的线程了。

你可以在BeginInvoke的方法中设置一个断点,然后打开VS的线程窗口,你就可以发现该线程不是发起操作的线程。

另外,你从MSDN里引用的那个对BeginInvoke的解释是对委托的BeginInvoke的解释:
Action download = () => Download();
download.BeginInvoke();
它会使用线程池上的一个线程执行
这个是跟IO操作的BeginXXX不一样的。这是由操作系统实现的。
我们打个比方,我们去数据库查询一堆数据,那么你发起这个请求后,查询请求发送到数据库服务器,这个时候你自己的机器是不需要关心查询的执行是不?那我们只要数据库查询完毕,然后结果返回时有个机制告诉我们查询完了,你来处理吧。这就是IO异步。这样我们在查询数据库期间我们的线程不会阻塞(等结果),那么这个线程就可以去干其他事儿了,这样就能创建更少的线程,干更多的事儿。更少的线程线程上下文切换的几率就更小,消耗的资源也更少。

使用异步IO就是,我们发起一个异步IO请求,然后我们的线程就立马返回了,当请求有了结果,操作系统再从线程池里弄一线程处理后续流程。对于FileStream.BeginRead()会不会创建新的线程还是不确定,但是经过查找资料后得知,Net ThreadPool类中的线程分为Worker ThreadI/O Thread。而Worker Thread可以看成.Net通过Thread类预先创建的一组线程。.NetThreadPool类中提供的方法,如QueueUserWorkItem, Timer, delegate回调等使用的都是Worker Thread。而.Net中对I/O操作的封装,如FileStream, NetworkStream等则是使用的IO ThreadIO Thread是对I/O专门提供的,效率更高些!


下一篇: 云计算开展趋势
上一篇: 压倒数据库的最后一根稻草
标签:

欢迎转载,转载时必须以链接形式注明来自 【南京典乐科技】
专业服务:南京网站建设,南京网站制作,南京网站设计,南京网站制作公司
咨询电话:13851941123(7*24小时在线服务)
公司网址:本文地址:http://m.025app.com/news/detail_209.html

 
公司简介 | 联系我们 | 知识中心
Copyright © 南京典乐科技 版权所有
苏ICP备12085975号
首页
咨询电话
联系我们