C#中Timers.Timer的stateinfo参数垃圾回收问题咨询
关于C#
Timers.Timer中state对象的GC回收问题 问题1:stateinfo(即new ei.StringID)是否会被C#自动回收?
会的。ei.StringID属于.NET托管对象,只要满足垃圾回收器(GC)的回收条件——没有任何存活的引用指向它,就会被GC自动回收。
问题2:它会在何时被回收?
回收时机完全取决于对象的引用持有情况,分以下几种场景:
- Timer回调执行完成后:如果回调执行结束后,没有其他代码再引用这个
stateinfo对象,GC会在下次执行垃圾回收操作时将其回收。 - Timer未触发就被丢弃:如果
MyEventNotification多次被调用,每次都会创建新的Timer并覆盖m_Timer,旧的Timer如果没有被手动调用Dispose(),它会一直持有旧的stateinfo引用,直到旧Timer本身被GC回收(此时旧的stateinfo也会失去引用,随之被回收)。 - Timer被手动释放:如果主动调用
m_Timer.Dispose(),Timer会释放对stateinfo的引用,之后只要没有其他引用指向该对象,GC就会将其回收。
额外代码优化提示
你的代码里有两个需要注意的细节:
- 每次创建新
Timer前,应该先释放旧的Timer,避免内存泄漏:
public void MyEventNotification(in MyEventInfo ei) { if (ei.State!=MyEventState.Completed) { // 先释放旧Timer资源 m_Timer?.Dispose(); m_Timer=new Timer(TimerHandler, ei.StringID, 1000, Timeout.Infinite); } }
- 回调里的类型转换要确保
ei.StringID确实是string类型,否则会抛出强制转换异常,建议做安全检查:
public void TimerHandler(Object stateinfo) { if(stateinfo is string id) { // 安全使用id做后续操作 if (m_JustForShow==1) { // 这里的代码运行在线程池线程中,并非创建Timer的线程,但只要当前类实例还存活,就可以访问成员变量(注意线程安全问题) } } }
内容的提问来源于stack exchange,提问作者user3161924
相关产品推荐
相关产品推荐

