如何避免从System.Threading.Timer在UI中调用时泄漏手柄? [英] How to avoid leaking handles when invoking in UI from System.Threading.Timer?

查看:150
本文介绍了如何避免从System.Threading.Timer在UI中调用时泄漏手柄?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这似乎是从一个System.Threading.Timer泄漏回调一个WinForms控制要求调用手柄,直到计时器设置。有没有人对如何解决这个想法?我需要相应地轮询值每秒,并更新用户界面。

It seems like calling Invoke on a winforms control in a callback from a System.Threading.Timer leaks handles until the timer is disposed. Does anyone have an idea of how to work around this? I need to poll for a value every second and update the UI accordingly.

我试图在一个测试项目,以确保这的确是泄漏的原因,这简直是以下内容:

I tried it in a test project to make sure that that was indeed the cause of the leak, which is simply the following:

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

这将泄漏2手柄/秒,如果你在Windows任务管理器看。

This will leak 2 handles/second if you watch in the windows task manager.

推荐答案

调用的行为像一个的BeginInvoke / EndInvoke会对的,因为它张贴消息到UI线程,创建了一个手柄,并等待在该手柄来确定时,调用手段齐全。正是这种处理是泄漏。你可以看到,这些都是使用的Process Explorer 不愿透露姓名的事件在应用程序运行时监控手柄

Invoke acts like a BeginInvoke/EndInvoke pair in that it posts the message to the UI thread, creates a handle, and waits on that handle to determine when the Invoked method is complete. It is this handle that is "leaking." You can see that these are unnamed events using Process Explorer to monitor the handles while the application is running.

如果IAsyncResult的是IDisposable接口,处置的对象会照顾清理手柄。由于它不是,手柄得到清理的垃圾收集器运行时并调用IAsyncResult对象的终结。您可以通过每20呼叫DoStuff后加入GC.Collect的()请参阅本 - 句柄计数降至每20秒。当然,解决的问题,加入调用GC.Collect的()是的错误的方式来解决这个问题;让垃圾收集器做自己的工作。

If IASyncResult was IDisposable, disposal of the object would take care of cleaning up the handle. As it is not, the handles get cleaned up when the garbage collector runs and calls the finalizer of the IASyncResult object. You can see this by adding a GC.Collect() after every 20 calls to DoStuff -- the handle count drops every 20 seconds. Of course, "solving" the problem by adding calls to GC.Collect() is the wrong way to address the issue; let the garbage collector do its own job.

如果你不这样做的需要的将Invoke调用是同步的,使用的BeginInvoke,而不是调用,并且不调用EndInvoke;最终结果将做同样的事情,但没有句柄将被创建或泄露的。​​

If you do not need the Invoke call to be synchronous, use BeginInvoke instead of Invoke and do not call EndInvoke; the end-result will do the same thing but no handles will be created or "leaked."

这篇关于如何避免从System.Threading.Timer在UI中调用时泄漏手柄?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆