ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c# – 如何正确处理Form,没有从被处置对象的另一个线程调用Invoke的风险?

2019-06-30 03:56:15  阅读:201  来源: 互联网

标签:c multithreading events winforms dispose


我有一个表单“监听”在其他地方提出的事件(不是表单本身,也不是其子控件之一).事件是由甚至在处理Form之后存在的对象引发的,并且可以在创建Form句柄的线程之外的线程中引发,这意味着我需要在事件处理程序中执行Invoke(以显示对事件的更改)形式,例如).

在表单的Dispose(bool)方法中(重写)我取消订阅了在调用此方法时仍可订阅的所有事件.但是,有时仍会从其中一个事件处理程序调用Invoke.我假设这是因为事件处理程序在事件被取消订阅之前被调用,然后OS切换控制执行的dispose方法,然后将控制权返回给处理器,该处理程序调用已处置对象上的Invoke方法.

锁定线程没有帮助,因为调用Invoke将锁定调用线程,直到主线程处理调用的方法.这可能永远不会发生,因为主线程本身可能正在等待调用Invoke调用线程所占用的对象的锁定释放,从而产生死锁.

因此,简而言之,当订阅外部事件时,如何正确处理表单,这可能会在不同的线程中引发?

以下是一些关键方法的现状.这种方法遇到了我上面描述的问题,但我不确定如何纠正它们.

这是一个处理模型数据部分更改的事件处理程序:

private void updateData()
{
 if (model != null && model.Data != null)
 {
  model.Data.SomeDataChanged -= new MyEventHandler(updateSomeData);

  model.Data.SomeDataChanged += new MyEventHandler(updateSomeData);
 }
 updateSomeData();
}

这是一个必须对视图进行更改的事件处理程序:

private void updateSomeData()
{
 if (this.InvokeRequired) this.myInvoke(new MethodInvoker(updateSomeData));
 else
 {
  // do the necessary changes
 }
}

和myInvoke方法:

private object myInvoke(Delegate method)
{
 object res = null;
 lock (lockObject)
 {
  if (!this.IsDisposed) res = this.Invoke(method);
 }
 return res;
}

我重写Dispose(bool)方法:

protected override void Dispose(bool disposing)
{
 lock (lockObject)
 {
  if (disposing)
  {
   if (model != null)
   {
    if (model.Data != null)
    {
     model.Data.SomeDataChanged -= new MyEventHandler(updateSomeData);
    }
    // unsubscribe other events, omitted for brevity
   }
   if (components != null)
   {
    components.Dispose();
   }
  }
  base.Dispose(disposing);
 }
}

更新(根据Alan的要求):

我从不显式调用Dispose方法,我让它由框架完成.到目前为止,仅在应用程序关闭时才发生死锁.在我进行锁定之前,我有时会在表单被关闭时抛出一些异常.

解决方法:

有两种方法需要考虑.一种是在Form中有一个锁定对象,并且在锁内发生对Dispose和BeginInvoke调用的内部调用;因为Dispose和BeginInvoke都不需要很长时间,因此代码永远不必等待很长时间.

另一种方法是声明由于Control.BeginInvoke / Form.BeginInvoke中的设计错误,这些方法有时会抛出一个实际上无法防止的异常,并且只有在无论是否无关紧要的情况下都应该被吞下该动作发生在无论如何已被处置的表格上.

标签:c,multithreading,events,winforms,dispose
来源: https://codeday.me/bug/20190630/1332820.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有