我使用 Visual Studio 2013 构建了一个具有单个表单的 C# 应用程序,并且该应用程序有两个更新屏幕的例程。更新屏幕的例程需要在主线程上运行,因此我自己的线程(不与屏幕交互)在需要更新时调用主窗体上的 BeginInvoke 方法。然而,应用程序中的某个地方发生了一些事情,导致两个更新例程停止执行。我已将日志记录到应用程序中以跟踪对 BeginInvoke 的调用以及更新例程的执行,并且我可以看到,当发生此问题时,会进行 BeginInvoke 调用,但随后什么也没有发生。当这种情况发生时,整个应用程序似乎冻结了。我想不出可能是什么原因造成的。我该如何调试这个?有什么方法可以查看主线程上排队运行的内容吗?当我在调试中运行并闯入应用程序时,所有线程看起来都很正常,并且主线程似乎没有执行任何操作,那么为什么它不处理我的待处理更新任务呢?
Control.BeginInvoke() 将委托添加到内部线程安全队列。并向 UI 线程发布一条消息,告诉它去查看该队列。 Application.Run() 内的消息循环获取该消息并再次清空队列,执行委托。
因此,如果您没有看到这种情况发生,那么最明显的原因是 UI 线程不在 Application.Run() 循环内。例如,您可能犯的一个标准错误是等待线程完成。很有可能造成死锁。永远不要等待,如果您需要在线程完成后运行代码,请考虑BackgroundWorker的RunWorkerCompleted事件或TaskScheduler.FromCurrentSynchronizationContext()。
没有看到任何事情发生的不太明显的失败模式是您过于频繁地调用 BeginInvoke() 。如果您每秒执行此操作超过约 1000 次,无论给予还是接受,那么您就会用太多的委托淹没该内部队列。 UI 线程实际上会忙于清空该队列,但永远无法跟上,总是在执行一个委托后在队列中找到另一个委托。当这种情况发生时,它会变得紧张,不再履行其正常职责。就像响应输入和绘制窗口一样。除了限制调用 BeginInvoke() 的速率之外,没有解决此问题的方法。请牢记目标,您只需按照用户眼睛可以感知的频率进行操作即可。以每秒超过 25 次的速度更新 UI 只是浪费精力。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)