在一次处理大量数据时避免在窗口中使用"(无响应)"标签

Foo*_*o42 12 c++ windows mfc

我偶尔需要从网络上的一个软件包处理大量数据,这需要足够长的时间,当用户尝试与应用程序窗口交互时,将"(无响应)"字符串添加到窗口标题中.我知道这是因为处理是在一个处理消息的调用中完成的(在堆栈的某个方向上),因此阻止了消息泵.我也知道解决这个问题的理想方法是在一个单独的线程中异步处理数据,以便泵可以继续运行,但这是一个大型桌面应用程序,从顶部到脚趾单线程,并安全地关闭此处理在我们的时间框架内是不可行的.

所以考虑到这一点,是否有任何机会我至少可以通过告诉Windows我的应用程序即将开始繁忙之前至少避免"无响应"的名字对象(大多数用户读作"已经崩溃")工作?我相信在回应关闭请求时会有这样的问题,人们可以继续要求窗口有更多时间来避免它宣称你没有"及时关闭"

我应该添加这是一个C++ MFC应用程序.

Fre*_*ool 16

我不认为Windows API可以帮助您.

或者,如何显示带有进度条的对话框并使其在单独的线程中运行?

对话框中的"此操作可能需要半小时"的文本也可能是合适的.


Sma*_*acL 10

好吧,首先我赞成弗雷德里克的帖子,因为无论喜欢与否,第二个主题可能是最好的方式.

但是,如果您真的不想走这条路,您可以手动在应用程序内循环中抽取消息队列.像这样的东西;

int Refresh()
{
    MSG       msg;
    if (PeekMessage (&msg, NULL, 0, 0,PM_NOREMOVE))
        if ((msg.message == WM_QUIT) 
          ||(msg.message == WM_CLOSE) 
          ||(msg.message == WM_DESTROY) 
          ||(msg.message == WM_NCDESTROY)
          ||(msg.message == WM_HSCROLL)
          ||(msg.message == WM_VSCROLL)
          ) 
          return(1); 
    if (PeekMessage (&msg, NULL, 0, 0,PM_REMOVE))
    {
        TranslateMessage (&msg);
        DispatchMessage (&msg);
    }
    return(0);
}
Run Code Online (Sandbox Code Playgroud)

这实际上是我在重写类似单独线程之前使用的一段代码.基本上我看看队列,过滤掉不需要的消息,然后发布其余的消息.它在某种程度上起作用,但偶尔引起一些令人讨厌的副作用,因此重写.


adz*_*dzm 9

您不必对来自PeekMessage的消息执行任何操作.只需调用PeekMessage,您甚至不必从队列中删除任何内容或处理它.只要每5秒左右调用一次,就会导致窗口认为该过程仍然响应.

另一个想法是在通知托盘中显示一个单独的进程/线程,并通知用户进程正忙于等待内部操作完成.您将在Visual Studio,SQL Server Management Studio等更高版本中看到这些内容.


Duc*_*tro 7

Win32有一个方法user32.dll.

DisableProcessWindowGhosting()

禁用调用GUI进程的窗口重影功能.窗口重影是一种Windows管理器功能,允许用户最小化,移动或关闭未响应的应用程序的主窗口.

除了上面记录的行为之外,我还在这里(在C#应用程序中)验证了此Win32调用还可以防止Not Responding标签出现在窗口上.

我在这里通过C#回答类似问题找到了这个:https://stackoverflow.com/a/15380821/29152.

  • @SamB可能会更糟糕的用户体验,但它仍然是OP正在寻找的直接答案.我不得不自己研究一个不同的,更合理的原因,这是一个Windows认为没有响应的全屏游戏 - 全屏应用程序执行长时间加载,已经提供"加载..."反馈到用户.在这种情况下,Windows不希望做更多的事情. (2认同)

use*_*913 5

如果你分叉一个线程,你很可能会担心其他一些用户动作发生,这可能取决于长时间运行的结果(是的,并发).因此,扩展Fredrick所说的内容,如果你创建了一个新线程并设置了一个进度条,你可以将焦点锁定在进度条上,以阻止用户与应用程序的其余部分进行交互.这应该足以实现一个非常简单的第二个线程而不必担心并发性,因为你实际上是通过禁用用户交互来锁定应用程序的其余部分.