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

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

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知道线程仍在处理”? 我的电子邮件线程是否会一直运行完成,或者是否存在exception终止的危险?

来自System.Threading.Thread

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

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

查看System.Threading.Thread.IsBackground的文档

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

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

这可以更精确地说明:

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

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