在Winform之类桌面程序中当用线程更新界面控件时,需要使用类似这样的代码this.Invoke。

在调用之前还需要作InvokeRequired判断,还需要定义一个delegate,会降低编码效率.

有时后台线程还没有结束,我们关闭了安全窗体,虽然窗体关闭了,但是我们的后台线程还在运行。这样会报错,如下图:

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

抛出InvalidOperationException异常。

2、无法访问已释放的对象。

抛出ObjectDisposedException异常。


推荐解决办法:

1、首先定义一个扩展方法

public static class UIThreadExtensions
{
        public static void InvokeOnUiThreadIfRequired(this Control control, Action action) 
        {
            try
            {
                if (!control.IsDisposed)
                {
                    if (control.InvokeRequired)
                    {
                        control.Invoke(action);
                    }
                    else
                    {
                        action.Invoke();
                    }
                }
                else
                    Thread.CurrentThread.Abort();
            }
            catch (Exception ex)
            {
            }
        }
}

上面的扩展方法加了try-catch,就不会因为关闭了窗体,更新界面控件的还未结束的问题。

2、使用扩展方法

这样,在线程中需要操作控件的就中需要这样调用:

this.InvokeOnUiThreadIfRequired(() =>
{
 lblResult.Text = string.Format("共有{0}条链接,正在检查链接状态...", urlAllCount);
 lblResult.Visible = true;
});

这样关闭多线程的winform窗体就不会抛出ObjectDisposedException和InvalidOperationException异常了