.net 在CPU负载较重的情况下,跨线程开始阻塞

.net 在CPU负载较重的情况下,跨线程开始阻塞,.net,winforms,multithreading,.net,Winforms,Multithreading,我有一个Windows窗体用户控件,其中包含一个第三方图像显示控件,该控件使用BeginInvoke委托调用从单独的线程更新 在高CPU负载下,UI会锁定。当我附加调试器时,它总是在更新第三方映像控件的同一行代码上 public ICogImage DisplayImage { get { return this.ResultImageCogDisplay.Image; } set { this.BeginI

我有一个Windows窗体用户控件,其中包含一个第三方图像显示控件,该控件使用BeginInvoke委托调用从单独的线程更新

在高CPU负载下,UI会锁定。当我附加调试器时,它总是在更新第三方映像控件的同一行代码上

    public ICogImage DisplayImage
    {
        get { return this.ResultImageCogDisplay.Image; }
        set 
        {
           this.BeginInvoke((ThreadStart)delegate
            {
                this.ResultImageCogDisplay.Image = value;
            });

        }
    }
如果我注释掉setter的实现,那么问题就消失了

有人能解释为什么会发生这种情况吗?

更多信息:

  • 图像更新事件从帧采集卡定期生成(~200ms)。事件在单独的线程上引发
  • 我相信第三方图像控件使用ActiveX,它是来自Cognex的视觉处理框架的一部分
  • 图像约为900x800 8位灰度
  • 表单上有4个这样的控件,每个控件从具有不同图像的不同线程馈送
  • 我尝试过使用和不使用IsInvokeRequired()检查,似乎没有任何区别

我在高CPU负载下访问的PostMessage队列上的消息数量是否有任何限制?
BeginInvoke
将要在UI线程上执行的操作排队。如果你把足够多的事情排成队列,以致于UI无法跟上它们,那么你将压倒UI线程,它将出现挂起状态。尝试将事件限制回每秒一次,以查看是否有帮助。

BeginInvoke
将要在UI线程上执行的操作排队。如果你把足够多的事情排成队列,以致于UI无法跟上它们,那么你将压倒UI线程,它将出现挂起状态。尝试将事件限制回每秒一次,看看是否有帮助。

Windows消息队列条目(至少在32位系统上)确实有10000个条目的限制。在这种情况发生之前很久,通过发布消息的速度比GUI处理消息的速度快,很容易对GUI进行屏蔽-我经常这样做:((


通常,我的设计使用一个对象池来进行线程间通信,因此我避开了这个问题,因为如果GUI返回“已使用”对象的速度不够快,则生成线程会在池队列上被阻塞,从而提供了总体流控制。当然,在停止GUI锁定时,如果您有这样的帧速率要求,这并没有多大帮助无法满足:(

Windows消息队列条目(至少在32位系统上)确实有10000个条目的限制。在这之前很久,通过发布消息的速度比GUI处理消息的速度快,很容易对GUI进行屏蔽-我经常这样做:((


通常,我的设计使用一个对象池来进行线程间通信,因此我避开了这个问题,因为如果GUI返回“已使用”对象的速度不够快,则生成线程会在池队列上被阻塞,从而提供了总体流控制。当然,在停止GUI锁定时,如果您有这样的帧速率要求,这并没有多大帮助无法满足:(

是否可以找到此队列上的邮件数,以证明其原因?我在队列上发布的图像数据量是否是一个因素(我可以缩小图像比例)。不幸的是,应用程序必须显示用于制造过程质量保证的图像。数据量、数据处理速度等是UI线程能否跟上的一个因素。我认为没有办法证明这一点,但如果数据量减少,问题就会得到缓解。请尝试p将
控制台。WriteLine
加载到捕获
日期时间的UI线程。现在发布代码并将其从
日期时间中减去时,现在可以确定代码实际执行的时间。然后可以确定UI线程正在经历的大致延迟。如果需要更精确,请尝试使用
StopWatch
相反。是否可以找到此队列上的邮件数,以证明其原因?我在队列上发布的图像数据量是否是一个因素(我可以缩小图像比例)。不幸的是,应用程序必须显示用于制造过程质量保证的图像。数据量、数据处理速度等是UI线程能否跟上的一个因素。我认为没有办法证明这一点,但如果数据量减少,问题就会得到缓解。请尝试p将
控制台。WriteLine
加载到捕获
日期时间的UI线程。现在发布代码并将其从
日期时间中减去时,现在可以确定代码实际执行的时间。然后可以确定UI线程正在经历的大致延迟。如果需要更精确,请尝试使用
StopWatch
取而代之。我将BeginInvoke更改为Invoke,因为我认为它会阻止调用方法,直到更新完成(同步)-但是它没有任何不同。上面的DisplayImage属性是从大约3-4个级别的事件处理程序更新的,其中一些使用Delegate.BeginInvoke(),这(AFAIK)使用与您使用的线程池类似的线程池-但是您可以对池大小有更多的控制。我可以使用framegrabber进行数字I/O握手,我可以使用它跳过/拒绝下一个正在检查的产品,因此如果我可以将图像更新速度减慢到可接受的速度(这不会挂起UI)然后我可能会有一个解决方案。感谢您的帮助。从BeginInvoke更改为Invoke可能不会减少工作负载;但可能确实意味着队列没有过载。Invoke只是阻止当前线程并让UI调用该操作。如果您仍然有挂起问题,则设置DisplayImage的工作负载d显示图像的速度可能不会超过每秒4-5次。不是吗