当原始类超出范围时,线程会发生什么

时间:2015-05-18 20:29:48

标签: c# .net multithreading

为了清楚起见,我简化了下面的例子,但是我在现场制作程序中遇到了这个,我看不出它会如何工作!

public class Test
{
    static void Main() 
    {
        Counter foo = new Counter();
        ThreadStart job = new ThreadStart(foo.Count);
        Thread thread = new Thread(job);
        thread.Start();
        Console.WriteLine("Main terminated");
    }
}

public class Counter
{
    public void Count()
    {
        for (int i = 0; i < 10; i++)
        {
            Console.WriteLine("Other thread: {0}", i);
            Thread.Sleep(500);
        }
        Console.WriteLine("Counter terminated");
    }
}

主程序启动计数器线程,主程序终止。无论给出以下输出,计数器线程都会继续运行。

Main terminated    
Other thread: 0
Other thread: 1
Other thread: 2
Other thread: 3
Other thread: 4
Other thread: 5   
Other thread: 6
Other thread: 7    
Other thread: 8    
Other thread: 9
Counter terminated

我的示例程序演示了虽然调用类不再存在,但线程仍然存活完成。但是,我的理解是,一旦一个类超出范围,它的资源最终将被垃圾收集整理。

在我的现实生活场景中,该线程进行了大量的电子邮件持续1-2小时。我的问题是“垃圾收集最终会杀死线程还是GC知道线程仍在处理”?我的电子邮件线程是否会一直运行完成,或者是否存在异常终止的危险?

4 个答案:

答案 0 :(得分:12)

来自System.Threading.Thread

  

启动线程后,不必保留对Thread对象的引用。线程继续执行,直到线程过程完成。

因此,即使Thread对象未被引用,该线程仍将运行。

答案 1 :(得分:9)

查看System.Threading.Thread.IsBackground

的文档

如果一个线程不是后台线程,它将使应用程序不会关闭直到它完成。

答案 2 :(得分:8)

  

但是,我的理解是,一旦一个类超出范围,它的资源最终将被垃圾收集整理。

这可以更准确地说明:

一旦通过托管引用无法从任何可执行代码访问对象实例,它就有资格进行垃圾回收。

当您创建一个执行特定对象方法的新线程时,您可以在该线程的生命周期内访问该对象的内容。如果GC能够证明任何应用程序的线程不再可能再次访问该对象,则GC只能清理它。由于您的代码 仍然可以访问对象实例,因此它不会获得GCed。

答案 3 :(得分:0)

变量的范围供编译器确定是否可以通过其他方法访问该变量。线程是由运行时控制的运行对象。