隐藏

完美解决c#关闭多线程的winform窗体不抛出ObjectDisposedException异常

发布:2020/12/21 10:28:38作者:管理员 来源:本站 浏览次数:1455

winform程序中当用多线程的时候,一般线程会更新界面控件,类似这样的代码this.Invoke。有时后台线程还没有结束,我们关闭了安全窗体,虽然窗体关闭了,但是我们的后台线程还没有还在运行。这样会报错,如下图:

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


抛出InvalidOperationException异常。

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


抛出ObjectDisposedException异常。

我的解决办法:

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

我们知道如果不是在UI线程操作控件会报错, 我们要通过this.Invoke来把消息传递给UI线程,在UI线程操作。有可能我们代码中会用很多这样的this.Invoke代码 ,不可能都加上InvokeRequired这样的判断,所以我定义一个扩展方法如下:


  1. public static class ControlExtensions
  2. {
  3. public static void InvokeOnUiThreadIfRequired(this Control control, Action action)
  4. {
  5. try
  6. {
  7. if (!control.IsDisposed)
  8. {
  9. if (control.InvokeRequired)
  10. {
  11. control.Invoke(action);
  12. }
  13. else
  14. {
  15. action.Invoke();
  16. }
  17. }
  18. else
  19. Thread.CurrentThread.Abort();
  20. }
  21. catch (Exception ex)
  22. {
  23. }
  24. }
  25. }


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

2、使用扩展方法

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

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


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