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

时间:2021-10-02 01:56:55

I simplified the example below for the sake of clarity, but I came across this in a live production program and I cannot see how it would be working!

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

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");
    }
}

The main routine starts the counter thread and the main routine terminates. The counter thread carries on regardless giving the following output.

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

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

My example program demonstrates that although the calling class no longer exists, the thread survives to completion. However, my understanding is that once a class is out of scope, its resources will eventually be tidied up by garbage collection.

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

In my real life scenario, the thread does a mass Emailing lasting 1-2 hours. My question is "Would garbage collection eventually kill off the thread or will GC know that the thread is still processing"? Would my Emailing thread always run to completion or is there a danger it will terminate abnormally?

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

3 个解决方案

#1


12  

From System.Threading.Thread

It is not necessary to retain a reference to a Thread object once you have started the thread. The thread continues to execute until the thread procedure is complete.

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

So even if the Thread object is unreferenced, the thread will still run.

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

#2


9  

Have a look at the documentation for System.Threading.Thread.IsBackground

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

If a thread isn't a background thread, it will keep the application from shutting down until it's done.

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

#3


8  

However, my understanding is that once a class is out of scope, its resources will eventually be tidied up by garbage collection.

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

This can be stated more precisely:

这可以更精确地说明:

Once an object instance is no longer accessible from any executable code through a managed reference, it becomes eligible for garbage collection.

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

When you create a new thread that is executing a particular object's method you're making that object's contents accessible throughout that thread's lifetime. The GC can only clean it up if it's able to prove that it is no longer possible for any of the application's threads to ever access that object again. Since your code can still access the object instance, it doesn't get GCed.

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

#1


12  

From System.Threading.Thread

It is not necessary to retain a reference to a Thread object once you have started the thread. The thread continues to execute until the thread procedure is complete.

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

So even if the Thread object is unreferenced, the thread will still run.

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

#2


9  

Have a look at the documentation for System.Threading.Thread.IsBackground

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

If a thread isn't a background thread, it will keep the application from shutting down until it's done.

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

#3


8  

However, my understanding is that once a class is out of scope, its resources will eventually be tidied up by garbage collection.

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

This can be stated more precisely:

这可以更精确地说明:

Once an object instance is no longer accessible from any executable code through a managed reference, it becomes eligible for garbage collection.

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

When you create a new thread that is executing a particular object's method you're making that object's contents accessible throughout that thread's lifetime. The GC can only clean it up if it's able to prove that it is no longer possible for any of the application's threads to ever access that object again. Since your code can still access the object instance, it doesn't get GCed.

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