【问题标题】:How does the WM_PAINT get processed while Parallel.For is not finished yet? [duplicate]当 Parallel.For 尚未完成时,如何处理 WM_PAINT? [复制]
【发布时间】:2018-10-24 20:30:51
【问题描述】:

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

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 次运行,它从未崩溃过。所以这次调试器似乎不是我的朋友。

【问题讨论】:

  • 只有在 VS 调试器中才会出现这种情况吗?我注意到调用通过 DebuggableCallback 进行,我认为它是由 Visual Studio 本身调用的,当您的程序在没有附加调试器的情况下运行时不会被调用。
  • 顺便说一句,我会将someBitmap.UnlockBits 调用放在finally 块内。
  • @Dai:看来你是对的。它不会在调试器之外发生(至少在我刚刚尝试的最后 6 次运行中)

标签: c# .net multithreading blocking ui-thread


【解决方案1】:

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

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

【讨论】:

  • 天哪...我不知道这个
  • 不客气。我在调试这些东西方面有相当的份额;-)。这里有更严重的问题。
猜你喜欢
  • 2015-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-19
相关资源
最近更新 更多