更新 CListCtrl 时 MFC 应用程序冻结

Posted

技术标签:

【中文标题】更新 CListCtrl 时 MFC 应用程序冻结【英文标题】:MFC application freezing while updating CListCtrl 【发布时间】:2015-07-03 13:07:54 【问题描述】:

我的 MFC 应用程序中有一个 CListCtrl。当我从服务器收到一些通知时,需要更新列表。当通知较少时更新列表效果很好,因为列表上的操作较少。但是在负载过重的情况下,列表控制,然后应用程序会冻结。

我知道在批量更新的情况下会在单独的线程中更新 UI 项目,但在这种情况下,我的通知可以以任何顺序和任何数量出现,我需要以这样的方式处理,即我的主线程没有被阻止。

如果有人之前遇到过这个问题,请提出这个案例的方法。

【问题讨论】:

嗯 ... UI 冻结,因为消息循环无法对即将发生的事件采取行动。您必须将需要一些时间才能完成的函数移到工作线程中。 ......嗯......也可能有另一种方式,但我不确定。也许可以在函数中的单独消息循环中处理即将发生的事件。但这可能是糟糕的设计并导致其他陷阱孔。 CListCtrl 通常用于显示要从中选择的项目列表,这意味着一个很小的相当静态的列表。在我看来,CListCtrl 不适合您要完成的工作。我将研究CScrollView 方法,而不是CView,它具有处理滚动条的附加功能。然后有一个通知列表,随着通知的到来而更新,并在可视区域中显示这些通知。换句话说,采用更多的文档视图方法,其中文档是通知列表。 您应该考虑使用virtual CListCtrl。这种控制风格适用于大量数据,用于缓存数据并仅显示需要的数据。 【参考方案1】:

您可以将所有更新放入队列中。然后在 OnIdle 函数中从队列到控件进行有限数量的更新。当您的 GUI 消息队列为空时,将调用 OnIdle。它最多可以进行 20 次更新,然后返回。主线程将处理任何 GUI 输入,并在完成后再次调用 OnIdle。通过这种方式,您可以在保持 GUI 活跃的同时延迟和分散更新。

【讨论】:

【参考方案2】:

我遇到了类似的情况,并使用计时器解决了它。只有当 Timer 打勾时,ListCtrl 才会更新。

旁注:你应该这样做

SetRedraw(FALSE);

批量更新之前

SetRedraw(TRUE);

之后。

在进行批量操作时,您不应该让控件在一项一项级别上自行绘制。

【讨论】:

【参考方案3】:

使用线程。我遇到了同样的问题,我只是通过在线程函数中将元素添加到 clistctrl 的循环来解决它。也就是说,线程中的 POSTMESSAGE() 函数是否应该在我们想要添加元素的时候被调用。 MFC Application getting stuck when adding list control elements 另请参阅上面的链接以获得一些想法

【讨论】:

以上是关于更新 CListCtrl 时 MFC 应用程序冻结的主要内容,如果未能解决你的问题,请参考以下文章

MFC CListCtrl 更新任何单元格的文本

CListCtrl (MFC) 选择点击通过控制UNDERNEATH列表

如何在 SDI 中使用 MFC CListCtrl

使用 MFC 的 YouTube 下载器

MFC:CListCtrl.EnableWindow(FALSE),但仍可滚动? [复制]

MFC总结之CListCtrl用法及技巧