代码之家  ›  专栏  ›  技术社区  ›  Thomas Weller

在并行的情况下,如何处理WMèPAINT。For尚未完成[[副本]

  •  4
  • Thomas Weller  · 技术社区  · 6 年前

    在这样一个程序中有一些非最佳代码(伪代码给你一个想法):

    public void button1_click()
    {
         picturebox1.Image = someBitmap;
         someBitmap.LockBits(...);
         Parallel.For(..., () => DoSomethingWith(someBitmap));
         someBitmap.UnlockBits(...);
    }
    

    有时,程序崩溃,说位图已经被锁定。我不需要调试帮助,也不需要代码来修复问题。我很容易修好它。

    更让我困扰的是我不明白这是怎么发生的。IMHO UI线程被阻止。当 button1_click 方法正在执行。当然,除非有人打电话来 DoEvents() ,事实并非如此。

    不过,当我查看调用堆栈时,它显示了以下内容:

    1

    如你所见 Parallel.For() 调用仍在堆栈上。还没完成呢。.NET代码已到达ManualResetEventSlim,应等待。从 MSDN 我看不出 Wait() 方法执行消息调度。

    不过,在那一点上,一个 WM_PAINT 消息已被处理,导致图片框在位图仍被锁定时访问该位图 LockBits() .

    这是怎么回事?我对UI线程阻塞的理解哪里有错?

    @Dai

    1 回复  |  直到 6 年前
        1
  •  1
  •   Alois Kraus    6 年前

    有几种方法可以实现这一点:

    当你在等待的时候,一些信息还是被抽出来了。这包括调试程序似乎也使用的COM消息。 自.NET4.0以来,Windows窗体和WPF的消息泵送行为发生了多次更改。如果您有挂起的已发布消息,则通过UI自动化库调用您的应用程序时,它随时都会命中您的应用程序。

    推荐文章