C#Thread对象的生命周期

时间:2010-09-13 09:26:24

标签: c# multithreading object-lifetime

假设我有如下代码:

int Main()
{
    if (true)
    {
       new Thread(()=>
          {
              doSomeLengthyOperation();
          }).Start();
    }
    while (true)
    {
       //do nothing
    }
}

有2个线程,我将调用Main线程执行Main()函数的线程,并在“if”测试中将线程作为线程A新建。

我的问题是,线程A什么时候被销毁? do doSomeLenghtyOperation()能够完成吗?

由于没有指向线程A的引用,它是否会被标记为垃圾收集的候选者:

  1. 紧接在“new Thread()。Start()”语句本身完成后?
  2. 退出“if(true)”范围后立即?
  3. doSomeLengthOperation()运行完成后?
  4. 从不?
  5. 我看到的所有示例都是Main()持有引用,然后主线程在退出之前等待与线程A连接。我很好奇上面代码的生命周期是什么。

    提前致谢!

4 个答案:

答案 0 :(得分:12)

Thread对象一旦不再使用,即在调用Start方法后立即有资格进行垃圾收集。 (但是不会立即收集,因为垃圾收集器在特定时间运行。)

但实际线程并不依赖于Thread对象,即使收集了Thread对象,它也会继续运行。

如果主方法退出时线程仍在运行,则应用程序将不会在线程完成之前结束,除非您已将该线程标记为后台线程。

答案 1 :(得分:12)

单词“thread”在这里可能意味着几件事:

  • System.Threading.Thread对象(由new Thread()创建),
  • CLR线程(托管线程),
  • OS线程(非托管线程)。

一旦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通过引用将它保存在内存中。