C#使用扩展方法,实现在多线程环境下快捷的调用UI主线程窗体,不抛出InvalidOperationException异常
在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异常了