Dav*_*vy8 8 .net c# timer winforms handle-leak
似乎在System.Threading.Timer回调函数的回调中调用Winforms控件上的Invoke泄漏句柄,直到计时器被释放.有没有人知道如何解决这个问题?我需要每秒轮询一次值并相应地更新UI.
我在一个测试项目中尝试过,以确保这确实是泄漏的原因,这只是以下几点:
System.Threading.Timer timer;
public Form1()
{
InitializeComponent();
timer = new System.Threading.Timer(new System.Threading.TimerCallback(DoStuff), null, 0, 500);
}
void DoStuff(object o)
{
this.Invoke(new Action(() => this.Text = "hello world"));
}
Run Code Online (Sandbox Code Playgroud)
如果您在Windows任务管理器中观看,这将泄漏2个句柄/秒.
Invoke的行为类似于BeginInvoke/EndInvoke对,因为它将消息发布到UI线程,创建句柄,并等待该句柄以确定Invoked方法何时完成.这个句柄正在"泄漏".您可以看到这些是未命名的事件,使用Process Explorer在应用程序运行时监视句柄.
如果IASyncResult是IDisposable,则处理对象将负责清理句柄.事实并非如此,当垃圾收集器运行并调用IASyncResult对象的终结器时,句柄会被清理干净.你可以通过在每20次调用DoStuff后添加一个GC.Collect()来看到这一点 - 句柄计数每20秒就会下降一次.当然,通过添加对GC.Collect()的调用来"解决"问题是解决问题的错误方法.让垃圾收集器做自己的工作.
如果您不需要将Invoke调用设置为同步,请使用BeginInvoke而不是Invoke,并且不要调用EndInvoke; 最终结果将做同样的事情,但不会创建或"泄露"句柄.