如何欺骗Windows认为你的应用程序仍然很忙,尽pipe它没有响应

我的应用程序是一个窗口应用程序,执行某些复杂的mathalgorithm。 因为我很久以前就开始使用该应用程序,所以大部分仍然是单线程的。 更确切地说,主线程执行所有复杂的计算逻辑。 在计算过程中,我提到在屏幕上显示一些进展是很重要的。

在大多数情况下,mathalgorithm只需要几秒钟,因此在用户启动操作之后,会显示一个沙漏(或Windows 7中的运行圆),几秒钟后显示结果。

在某些情况下,algorithm可能需要几分钟的时间。 在这段时间里,我显示沙漏,algorithm很忙,我在窗口中显示进度。 但是,如果用户在忙了一段时间之后点击应用程序,则窗口变得“更白”(就像在窗口上放置了不完全透明的塑料片一样),窗口不再被更新,并且Windows报告“该应用程序没有响应”。

我使用Qt,我使用Qt函数QWidget :: repaint强制重绘,而我的algorithm是繁忙的。 重绘工作一段时间,但如上所述,Windows似乎阻止了一段时间后。

什么是正确的方式告诉Windows,你的应用程序仍然忙,这样的窗口不断更新? 如果我input一个显式的消息循环,用户可能会在应用程序中触发其他不需要的操作。

  • 调用PeekMessage足够了吗?
  • 调用GetMessage就足够了?
  • 还是应该调用DispatchMessage? 如何防止用户启动另一个操作(实际上是阻止所有的用户input)
  • 每次更新我的窗口时,是否应该调用其中的一条消息,还是我可以限制自己每隔几秒钟调用一次(10秒?,30秒?)

请注意,将计算逻辑移至单独的线程当前不是一个选项。

我在Windows 7上使用Visual Studio 2010,并结合使用Qt 4.7。

Solutions Collecting From Web of "如何欺骗Windows认为你的应用程序仍然很忙,尽pipe它没有响应"

您应该将GUI与应用程序逻辑分开。 所有其他解决方案都是黑客。 把计算逻辑移到一个单独的线程可以轻松地用Qt来实现。

我假设有一个函数(让我们称之为execute() ),当被调用时执行所有这些耗时的数学运算。 一种选择是使用Qt Concurrent API在单独的线程中调用此函数,而不使用低级线程处理。

你需要的是QtConcurrent::run函数:

QtConcurrent :: run()函数在一个单独的线程中运行一个函数。 函数的返回值通过QFuture API提供。

(而不是简单的调用execute()来阻塞你的用户界面,你可以做下面的事情(让A是定义了execute()的类):

 QFuture<void> future = QtConcurrent::run(this, &A::execute); 

您可以使用QFutrureWatcher来获得有关函数何时完成的通知。

你可以简单地调用QApplication::processEvents() ,比如说每2或3秒左右。 这应该会触发重新绘制事件并刷新您的进度栏和其他元素。

类似的问题和大量的信息在这里: 我需要一个消息泵,不会弄乱我打开的窗口

然而,正如你可能已经知道的那样,这是相当的黑客行为,将代码移动到另一个线程会更好。 为什么这是“不是一个选择”?

DisableProcessWindowGhosting函数(请参阅http://msdn.microsoft.com/zh-cn/library/ms648415(v=vs.85).aspx )告诉Windows,如果应用程序没有响应,则不会显示“虚幻窗口” 。

我的同事做了一些实验,注意到以下几点:

  • 显示进度的动画继续很好(这实际上是我想要实现的)
  • 用户仍然可以最小化,移动,…窗口(伟大)
  • 不利的一面:如果应用程序真的挂起,用户必须使用任务管理器来杀死它

所以,这解决了我的问题。