首页 新闻 会员 周边

c# 中线程可以重用吗?

0
悬赏园豆:10 [已解决问题] 解决于 2013-11-17 11:11

比如一个线程执行完了一个任务后自然终止,或者我调用abort方法让它终止后,它的IsAlive已经变为false后,能否再次运行同样的任务呢?也就是能否再次被Restart呢?

我不太想new一个新线程,既然这个线程已经闲下来了,应该可以再用的吧?

空明流光的主页 空明流光 | 初学一级 | 园豆:106
提问于:2013-11-16 10:53
< >
分享
最佳答案
0

.Net 中表示线程的类 Thread 一旦终止,它就无法通过再次调用 Start 来重新启动。.Net Thread 终止,“闲下来”的不是 .Net Thread,而是 Windows Thread Pool 中的线程。建议你阅读以下章节:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms686756(v=vs.85).aspx

已创建的线程会关联到 I/O completion 队列,当一个线程执行完自己的任务后,会被设置为 alertable wait 状态,此时已为线程分配的数据结构会被保留,当有请求被投递到 I/O completion 队列后,系统会通过一定的算法找出一个合适的处于 alertable wait 状态的线程,并将任务委派给它。

我不知道你们公司的程序是具有什么特性,但是要提高性能,简单来说,你需要区分I/O和非I/O(CPU密集型)操作。对于I/O操作,在 .Net 中应该使用类的 BeginXXX (比如:FileStream.BeginRead)形式的 API 来调用;对于非 I/O 操作,应该尽可能将任务细化,然后通过并行的方式执行(使用 Thead Pool或使用 PPL,TPL)。

当然,除了Thread Pool采用的抢先式计划模型,你也可以采用协作式计划模型,比如 Microsoft CCR and DSS(.Net)、Concurrency Runtime(C++)。

我的回答都只是蜻蜓点水,只是简单的提供一些资料,并不能直接解决你的问题。

 

收获园豆:2
Launcher | 高人七级 |园豆:45045 | 2013-11-17 10:40
其他回答(5)
0

完全可以,只要对象没被销毁就不需要重新来过,不过如果线程数目动态改变的话用线程池不错

收获园豆:2
大芝麻 | 园豆:4 (初学一级) | 2013-11-16 11:07

关键是怎么弄啊,哪个方法呀?

支持(0) 反对(0) 空明流光 | 园豆:106 (初学一级) | 2013-11-16 12:13

@沧海一杰: http://www.cnblogs.com/wildman/archive/2008/08/22/1274170.html#commentform

看了就知道怎么弄了,.net环境下很简单。

至于单个线程暂停重启可以用这个http://blog.sina.com.cn/s/blog_49c211fa010190a4.html

支持(0) 反对(0) 大芝麻 | 园豆:4 (初学一级) | 2013-11-16 12:21

@大芝麻: 线程池有诸多限制,而且我的项目用线程池会显得更复杂,所以暂时用手动控制。

支持(0) 反对(0) 空明流光 | 园豆:106 (初学一级) | 2013-11-16 14:44
0

一般情况下应该用线程池(BackgroundWorker.DoWork, ThreadPool.QueueUserWorkItem 或 Task.Run),不应该自己 new Thread.

收获园豆:2
deerchao | 园豆:8367 (大侠五级) | 2013-11-16 14:22

@大芝麻: 这是你说的,微软可没这么说过,要不它就不用提供new方法了。

支持(0) 反对(0) 空明流光 | 园豆:106 (初学一级) | 2013-11-16 14:45

@沧海一杰: 这是Jeffrey Richter 在 CLR via C# 中说的,不是我说的。

支持(0) 反对(0) deerchao | 园豆:8367 (大侠五级) | 2013-11-16 15:15

@deerchao: ThreadPool.QueueUserWorkItem有线程调度。但是好像不支持前台线程

支持(0) 反对(0) 朝曦 | 园豆:1073 (小虾三级) | 2013-11-16 17:49
0

这个问题你写两行代码一试就清楚了。 

即使假设线程可以被重启,但实际上它已经被中止了(自然终止后手动abort),就目前的.Net线程实现来看,其底层的OS线程已经结束了, 即使重启也只能是再重开一个OS线程, 而你却担心那个new操作的开销 -- new一个线程实例的开销比起真正 start 一个线程简直可以无视。

收获园豆:2
Todd Pointer | 园豆:379 (菜鸟二级) | 2013-11-16 14:37

是这样啊

支持(0) 反对(0) 空明流光 | 园豆:106 (初学一级) | 2013-11-16 14:43

@沧海一杰: 关于线程池里的线程,当你指定的代码执行完之后, 线程并不退出,而是进入等待状态。 你可以通过各种 WaitHandle 来模拟这个东西, 比如 event.WaitOne(),然后当想再用时就 event.Set()。 但理论上线程这样做与线程池相比并不会有性能上的提升。 线程只要启动了最好是持续的干活, 好比养头牛却总让它睡觉没活干,白白浪费草料。

支持(0) 反对(0) Todd Pointer | 园豆:379 (菜鸟二级) | 2013-11-16 19:13
0

.NET本身提供线程池功能,就是为了线程的重用的。建议直接使用.NET的线程池。

收获园豆:2
ocean | 园豆:824 (小虾三级) | 2013-11-16 16:31

我们公司大量线程一般都不建议使用线程池,因为有性能问题。

支持(0) 反对(0) 空明流光 | 园豆:106 (初学一级) | 2013-11-16 17:15

@沧海一杰: 用线程池无法达到我需要的性能指标。

支持(0) 反对(0) 空明流光 | 园豆:106 (初学一级) | 2013-11-16 17:16

@沧海一杰: 我不知道你说的性能问题是什么,我认为是你们的用法不对。线程重用本身就应该使用线程池来实现,而.NET的自带实现显然要比你自己写一个线程池性能高。

支持(0) 反对(0) ocean | 园豆:824 (小虾三级) | 2013-11-17 13:22
0

谢谢大家,听了大家说的我对线程有了新的认识;对于线程池用得比较少,性能问题也只是前人所讲,并未在实际项目中真正测试过。

空明流光 | 园豆:106 (初学一级) | 2013-11-17 11:09
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册