在 Parallel.For 尚未完成时如何处理 WM_PAINT?

How does the WM_PAINT get processed while Parallel.For is not finished yet?

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

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

程序时不时崩溃,说位图已经被锁定。我不需要调试帮助,也不需要代码来解决问题。我可以轻松修复它。

更让我困扰的是我不明白这是怎么发生的。恕我直言,UI 线程被阻塞。在执行 button1_click 方法时,不应处理任何 windows 消息。当然,除非有人打电话给DoEvents(),否则不是这样。

不过,当我查看调用堆栈时,它显示如下:

如您所见,Parallel.For() 调用仍在堆栈中。它还没有完成。 .NET 代码达到了 ManualResetEventSlim,应该等待。从 MSDN 我看不到 Wait() 方法进行消息调度。

不过,在那一点上,一条 WM_PAINT 消息得到处理,导致图片框访问位图,而该位图仍被 LockBits() 锁定。

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

@Dai 询问这是否仅在调试期间发生。确实,这似乎是真的。我给它运行了 10 次,它从未崩溃过。看来调试器这次不是我的朋友了

有几种方法可以实现:

当您等待时,一些消息仍会被发送。这包括似乎也被调试器使用的 COM 消息。 自 .NET 4.0 以来,Windows Forms 和 WPF 的消息泵送行为发生了多次变化。如果您通过 UI 自动化库调用,如果您有未决的已发布消息,它可以随时访问您的应用程序。