当前位置: 首页 > 编程语言 > C#

C#学习教程:.NetGarbage会收集一个未引用的对象,但有一个正在运行的线程吗?分享

时间:2023-04-10 23:55:34 C#

.NetGarbage会收集一个未引用的对象,但有一个正在运行的线程吗?我有以下代码(为了便于阅读而减少):Mainclass:publicStartProcess(){Thinkerth=newThinker();th.DoneThinking+=newThinker.ProcessingFinished(ThinkerFinished);th.StartThinking();}voidThinkerFinished(){Console.WriteLine("Thinkerfinished");}Thinker类:公共类Thinker{privateSystem.Timers.Timert;公共委托voidProcessingFinished();公共事件ProcessingFinishedDoneThinking;BackgroundWorker后台线程;publicThinker(){}publicStartThinking(){t=newSystem.Timers.Timer(5000);//5秒计时器t.AutoReset=false;t.Elapsed+=newSystem.Timers.ElapsedEventHandler(t_Elapsed);t.开始();//启动一个后台线程做思考backgroundThread=newBackgroundWorker();backgroundThread.DoWork+=newDoWorkEventHandler(BgThread_DoWork);backgroundThread.RunWorkerAsync();}voidt_Elapsed(对象发送者,System.Timers.ElapsedEventArgse){DoneThinking();}BgThread_DoWork(objectsender,DoWorkEventArgse){//这里的工作应该持续不到5秒//如果它不这样做就会死掉t.Stop();完成思考();我最初预计会发生的是主类中的事件处理程序会阻止Thinker被垃圾收集,但显然情况并非如此。我现在想知道无论此线程是否“忙”,是否都会发生垃圾回收。换句话说,是否有可能在5秒超时到期之前收集垃圾?换句话说,垃圾收集器是否有可能在我的Thinker完成处理之前收集它?不,一个线程只要被引用就被认为是活动的,并且任何正在运行的线程都被认为是被引用的(IIRC一个正在运行的线程将其堆栈注册为GC根,并且该堆栈将引用该线程)。那就是说我正在看你的例子,我不明白你认为线程在哪里产生?不,正在运行的线程的堆栈充当了GC的根。只要线程在运行,这个堆栈就存在,所以线程本身在运行时不会被收集。这篇文章提到了(除其他外)GC的用途。为了节省时间,GC根是全局对象,静态对象,所有线程栈上的所有引用,所有包含引用的CPU寄存器。你的问题有点难回答。像Joel一样,据我所知,堆栈上没有任何引用计时器的内容,它本身是唯一引用线程的东西。鉴于此,人们会期望一组Thinker实例。我对此很好奇,需要更具体的解释可能会发生什么,所以我深入研究了Reflector。事实证明,System.Timers.Timer最终创建了一个System.Threading.Timer,它在内部创建了内部类TimerBase的一个实例。TimerBase派生自CriticalFinalizerObject,这是一种系统类型,可确保约束执行区域(CER)中的所有代码都将在实现类完全确定并被GC丢弃之前执行。TimerBase也是IDisposable并且它的dispose方法循环并自旋等待直到锁被释放。此时,我开始遇到外部代码,所以我不确定锁是如何初始化或释放的。然而,基于TimerBase类的编写方式、它派生自CriticalFinalizerObject的事实以及它在释放锁之前处理spinwait的事实,我认为可以安全地假设没有被任何东西引用的线程不会直到代码执行完毕。就是说……重要的是要注意它很可能会由GC处理……可能不止一次,因为终结会大大延长最终的对象收集过程。对于那些CriticalFinalizerObjects,如果有代码积极强制执行CER以确保它被完全执行,则最终化过程可能需要更长的时间。如果你的思考者需要一段时间才能执行,这可能意味着你有完全相反的问题。它们不是过早收集的对象,而是经过漫长的最终确定,并且它们引用的任何内容最终都在gen2中,并且存在相当长的一段时间,直到GC最终能够完全收集它们。如果我没看错(我可能要离开这里),它可以被收集,因为它目前没有做任何事情。如果您的start方法中有局部变量,并且该方法仍然存在,那么这些变量仍然在堆栈上“在范围内”,并为您的线程提供根。但是您使用的唯一变量是您的私有计时器,因为它植根于线程本身,并且线程在堆栈上没有任何东西,所以没有什么可以让它保持活动状态。我同意和不同意,如果对线程对象的引用丢失,线程将被终止并被垃圾收集。在您的情况下可能并非如此,因为它不直接使用线程并使用计时器。但是如果在线程中调用方法,方法结束时线程引用丢失,就会被GC回收。运行线程?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: