首页 新闻 会员 周边

.net开发中,为何将100多个任务放入线程池却只有一个线程顺序执行

0
悬赏园豆:50 [待解决问题]

public void setHeader(DirectoryInfo theDir, string yeMei, string position)
{
  DirectoryInfo[] subDirectories = theDir.GetDirectories();
  foreach (DirectoryInfo dirinfo in subDirectories)
  {
    setHeader(dirinfo, yeMei, position);
  }
  FileInfo[] fileInfo = theDir.GetFiles();
  foreach (FileInfo fInfo in fileInfo)
  {
    if (fInfo.Extension.Equals(".doc"))
    {
      FileInfo fi = new FileInfo(fInfo.FullName);
      ThreadPool.QueueUserWorkItem(o => insertHeader(fi, yeMei, position));
    }
  }
}
private void insertHeader(FileInfo fInfo, string yeMei, string position)
{
//写入页眉

}

文件夹中有100多个文件,想遍历然后给每个文件插入页眉,可是却是一个一个顺序执行

风筝飞的主页 风筝飞 | 初学一级 | 园豆:152
提问于:2013-01-31 09:20
< >
分享
所有回答(5)
0

线程池会根据你目前计算机的可用资源情况(比如:可用cpu内核数)来分配线程执行。。。因为如果你内核数只有2个,实际上线程池分配比较多的线程来执行该任务,多数线程也是在等待,并未实际运行,而这又增加了线程间切换上下文的开销。

 

请参考:http://www.cnblogs.com/heyuquan/archive/2012/12/16/2820775.html

滴答的雨 | 园豆:3660 (老鸟四级) | 2013-01-31 09:28

我查看可用线程200,可是使用的很少,都空闲的了

支持(0) 反对(0) 风筝飞 | 园豆:152 (初学一级) | 2013-01-31 09:30

@风筝飞:

说明你开启的任务执行的比较快。如果你开启的任务执行久的话,线程池会为此任务分配比较多线程。

你调用完ThreadPool.QueueUserWorkItem()方法并不是说就开启了一个线程,此时只是将任务插入线程池的全局队列中,待线程池判定有可有可用资源及空闲线程的时候就开启一个线程,该线程在全局队列中抽取任务并执行

支持(0) 反对(0) 滴答的雨 | 园豆:3660 (老鸟四级) | 2013-01-31 09:33

@滴答的雨: 可是执行的很慢啊,我是想一下把这100多个文档处理完,可实际是一个一个处理

支持(0) 反对(0) 风筝飞 | 园豆:152 (初学一级) | 2013-01-31 10:08

@风筝飞:

1、确实存在楼下说的资源竟用问题,磁盘一般只有一个嘛,导致处理会被串行化……

2、你计算机是几核的啊

支持(0) 反对(0) 滴答的雨 | 园豆:3660 (老鸟四级) | 2013-01-31 10:18

@滴答的雨: 双核的

支持(0) 反对(0) 风筝飞 | 园豆:152 (初学一级) | 2013-01-31 10:36

@风筝飞: 实际上任务是否能并行就在于逻辑内核,你内核只有两个也说明了同一时间只能2个线程跑,多的线程只会共用这两个线程交替执行于等待执行,所以效率提升一般也就20-40%。而你使用了io操作出现资源竟用的情况所以并行提升效率不会很明显。

 

并行性,出了要考虑逻辑内核外,还有计算机整体的并行支持。eg:有的硬盘支持并行,或计算机上配置多个硬盘。。打印机也类似……

 

但是你使用线程池或则Task可以增加你程序的扩展性(即:当你的程序在客户机上以多个核跑或支持并行的设备时,你的程序效率可直接得到提升)

支持(0) 反对(0) 滴答的雨 | 园豆:3660 (老鸟四级) | 2013-01-31 10:42

@风筝飞: 另外不要认为线程多就会并行执行,就你的情况,就算有100个线程也是大部分在等待。

你可以直接使用Thread来创建100个你的任务,但实际上这比ThreadPool还慢。微软弄哥个ThreadPool来管理线程,根据机器的可用资源来判断线程的使用,就是怕线程被到处乱使用。。

支持(0) 反对(0) 滴答的雨 | 园豆:3660 (老鸟四级) | 2013-01-31 14:12
1

你可以用ThreadPool.SetMinThreads来提升并行的线程数,例如ThreadPool.SetMinThreads(5,5) 则最少有5个线程会并行,而不是一个一个顺序执行。以上只是表面回答你的问题。事实上你用多线程去操作文件是完全错误的做法,因为这样不会提高效率,甚至会降低效率。原因简单来讲就是:你可以想象磁盘有个用来扫描文件的磁头,这个磁头的作用就是“定位文件”,而在多线程环境下,一会操作这个文件一会操作另外一个文件,磁头就在不停地切换位置,“疲于奔命”,这样还不如安心把一个文件处理好然后再处理下一个(也就是你说的顺序执行)。因此你完全可以发起一个线程,在这个线程里顺序的去修改每一个文件,这样完全可以的,不会影响到UI线程的体验。

水牛刀刀 | 园豆:6350 (大侠五级) | 2013-01-31 09:44

说的有理,只是我觉得这样太慢才会想到多线程

支持(0) 反对(0) 风筝飞 | 园豆:152 (初学一级) | 2013-01-31 10:10
0

I/O操作用IOCP来做,用于I/O操作的线程数设置为CPU核心数。

Launcher | 园豆:45045 (高人七级) | 2013-01-31 09:50
0

线程的执行,最好都还是由操作系统来控制的

chenping2008 | 园豆:9836 (大侠五级) | 2013-01-31 10:32
0

 应该是单个任务执行的时间太快了,你在insertHeader函数中写个Thread.Sleep(200);最好200这个具体数字可以随机,这样你监控时就能监控多个任务同时执行了。

小胆粗心 | 园豆:300 (菜鸟二级) | 2013-01-31 13:43

实际情况是他执行的很慢,所以我才想要增加并行性,以求总的执行的更快

支持(0) 反对(0) 风筝飞 | 园豆:152 (初学一级) | 2013-01-31 13:47

@风筝飞: 那换种思路,直接用Thread开线程,建议开10个以内,100个列表你给每个线程随意分配其中一组。

 

如果要操作共有资源注意保护哦。

支持(0) 反对(0) 小胆粗心 | 园豆:300 (菜鸟二级) | 2013-01-31 14:09
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册