【问题标题】:Cross thread BeginInvoke blocking under heavy CPU load重 CPU 负载下的跨线程 BeginInvoke 阻塞
【发布时间】:2012-08-14 22:53:23
【问题描述】:

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

在 CPU 负载过重的情况下,UI 会锁定。当我附加一个调试器时,它总是在更新第 3 方图像控件的同一行代码中。

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

        }
    }

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

谁能解释为什么会这样?

更多信息:

  • 图像更新事件由图像采集卡定期(约 200 毫秒)生成。这些事件在不同的线程上引发。
  • 我相信第 3 方图像控件使用 ActiveX,它是康耐视视觉处理框架的一部分。
  • 图像约为。 900x800 8 位灰度
  • 表单上有 4 个这样的控件,每个控件从不同的线程提供不同的图像。
  • 我已经尝试过使用和不使用 IsInvokeRequired() 检查,它似乎没有任何区别。

我在高 CPU 负载下遇到的 PostMessage 队列中的消息数量是否有任何限制?

【问题讨论】:

    标签: .net winforms multithreading


    【解决方案1】:

    BeginInvoke 将要在 UI 线程上执行的操作排队。如果你排队的事情太多,UI 跟不上它们,你会压倒 UI 线程,它会显得挂起。尝试将事件限制到每秒一次,看看是否有帮助。

    【讨论】:

    • 是否可以找到此队列中的消息数,作为证明其原因的一种方式?我在队列上发布的图像数据量是否会成为一个因素(我可以缩小图像)。不幸的是,该应用程序必须将图像显示为用于制造过程的 QA。
    • 数据量、数据处理速度等是影响UI线程能否跟上的因素。我认为没有办法证明这一点,但如果数据量减少并缓解问题会告诉你很多。
    • 尝试在发布代码时将Console.WriteLine 发布到捕获DateTime.Now 的UI 线程,并从代码实际执行的DateTime.Now 中减去它。然后,您可以确定 UI 线程正在经历的大致延迟。如果您需要更准确,请尝试改用StopWatch
    【解决方案2】:

    Windows 消息队列条目确实存在 10,000 个条目的限制(至少在 32 位系统上)。在此之前很久,通过发布消息的速度比 GUI 处理它们的速度更快来调整 GUI 是很容易的——我经常这样做:((

    通常,我的设计使用对象池进行线程间通信,所以我解决了这个问题,因为如果 GUI 没有足够快地返回“已使用”对象,则生产者线程会在池队列中被阻塞,因此提供整体流量控制。当然,在停止 GUI 锁定时,如果您有无法满足的帧速率要求,这将无济于事:(

    【讨论】:

    • 我从 BeginInvoke 更改为 Invoke,因为我认为它会阻止调用方法,直到更新完成(同步) - 但是它没有任何不同。话虽如此,上面的 DisplayImage 属性是从大约 3-4 级深的事件处理程序更新的,其中一些使用 Delegate.BeginInvoke() (AFAIK)使用类似于您使用的线程池 - 但您将拥有更多控制权超过池大小。
    • 我与抓帧器进行了数字 I/O 握手,我可以使用它来跳过/拒绝正在检查的下一个产品,所以如果我可以将图像更新速度减慢到可接受的速度(这不会挂起 UI)然后我可能有一个解决方案。感谢您的帮助。
    • 从 BeginInvoke 更改为 Invoke 可能不会减少工作量;但可能确实意味着队列没有超载。 Invoke 只是阻塞当前线程并让 UI 调用操作。如果您仍然遇到挂起问题,则设置 DisplayImage 和显示图像的工作量可能无法以每秒 4-5 次的速度完成。没有多少普通控件能够获得很大的“帧速率”,它们应该显示设置一次的静态图像。
    猜你喜欢
    • 2023-01-31
    • 1970-01-01
    • 2018-08-18
    • 2015-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多