假设我有如下代码:
int Main()
{
if (true)
{
new Thread(()=>
{
doSomeLengthyOperation();
}).Start();
}
while (true)
{
//do nothing
}
}
有2个线程,我将调用Main线程执行Main()函数的线程,并在“if”测试中将线程作为线程A新建。
我的问题是,线程A什么时候被销毁? do doSomeLenghtyOperation()能够完成吗?
由于没有指向线程A的引用,它是否会被标记为垃圾收集的候选者:
我看到的所有示例都是Main()持有引用,然后主线程在退出之前等待与线程A连接。我很好奇上面代码的生命周期是什么。
提前致谢!
答案 0 :(得分:12)
Thread
对象一旦不再使用,即在调用Start
方法后立即有资格进行垃圾收集。 (但是不会立即收集,因为垃圾收集器在特定时间运行。)
但实际线程并不依赖于Thread
对象,即使收集了Thread
对象,它也会继续运行。
如果主方法退出时线程仍在运行,则应用程序将不会在线程完成之前结束,除非您已将该线程标记为后台线程。
答案 1 :(得分:12)
单词“thread”在这里可能意味着几件事:
new Thread()
创建),一旦Start()方法完成,线程对象将成为GC的候选者,因为没有更多的引用。
当doSomeLengthyOperation()运行时,托管线程将保持活动状态。
微软MVP的James Kovacs引用article:
托管线程的生命周期是 独立于Thread对象 创造它,这是一件非常好的事情 那你不想要GC 终止一个仍然存在的线程 只是因为你失去了所有的工作 对相关线程的引用 宾语。所以GC正在收集 线程对象,但不是实际的 托管线程。
如果您想亲自体验,本文还包含一些有用的代码示例。
理论上,操作系统线程与托管线程没有一对一的关系。来自MSDN:
...复杂的主机可以使用CLR Hosting API针对同一操作系统线程调度许多托管线程,或者在不同操作系统线程之间移动托管线程。
然而,在实践中,CLR线程maps directly to a Windows thread today。
答案 2 :(得分:10)
什么时候线程A被破坏?
doSomeLengthyOperation
完成时。
doSomeLenghtyOperation()是否能够完成
是的,即使主线程存在,因为它不是后台线程。如果在主线程存在时启动线程之前将IsBackground属性设置为true
,则该线程也将停止。
答案 3 :(得分:0)
这是一个很好的问题!线程肯定会完成,你可以自己尝试一下。但是如果你在while中调用GC.Collect()会很有趣。根据Richter的C#通过CLR,它将被垃圾收集。
<强>更新强>
我相信它不会被垃圾收集,因为Thread.CurrentThread通过引用将它保存在内存中。