检测控件是否已被释放

18

在我的应用程序中,我有一个用户控件,使用线程池执行异步操作。 线程池方法的样子如下:

private void AsyncFunction(object state)
    {
        ... do the calculation
        //refresh the grid data on the UI thread
        this.BeginInvoke(new MethodInvoker(() =>
                                               {
                          ... update the ui 
                                               }));
    }

我的问题是,如果用户关闭对话框,则用户控件将被处理,并且我会收到以下异常:

在窗口句柄创建之前,不能在控件上调用Invoke或BeginInvoke。

你知道有没有一种方法可以检测对话框是否已被处理?我不想在控件上设置一个对话框关闭时设置的属性。还有其他解决方法吗?

谢谢,

Radu

3个回答

30

3
实际上它不能解决全部情况。请参见下面的链接:https://dev59.com/2m855IYBdhLWcg3wPBpx#4460737 - Nick

10
你可以使用 Control.IsDisposed 属性。
try
{
    if(!this.IsDisposed) 
    {
        this.BeginInvoke(new MethodInvoker(() =>

                      {
                                // update my control
                      }
          ));
    }
}
catch ( InvalidOperationException )
{
    // Do something meaningful if you need to.
}

在调用 BeginInvoke 之前,您需要检查 IsDisposed,因为如果控件已被释放,则会失败。 - max
@ironic: 你可以订阅“Disposing”事件,取消或等待所有异步操作完成。 - max
这不行,IsDisposed属性可能会在if()语句之后立即变为true,仍然会使BeginInvoke()失败。将测试移到lambda内部。 - Hans Passant
最大建议这样做,不是在讽刺 :) - ironic
在我的程序中,不仅存在竞态条件,在关闭期间,当IsDisposed仍为false时,BeginInvoke有时会抛出异常(声称窗口句柄尚未创建)。 - Qwertie
显示剩余5条评论

0

你可以尝试使用同步对象,比如 EventWaitHandle ,来通知工作线程主线程即将退出。然后工作线程就可以结束执行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接