3

我有一个 Inno Setup 安装,它执行一些耗时的“AfterInstall”操作。并且在执行此操作时,安装 GUI 完全冻结(似乎它的主事件循环未处理)。这不是一个令人愉快的最终用户体验,所以也许这个操作有可能不冻结 GUI?就像在单独的线程中执行它或定期调用类似的东西handleGuiEventLoop()

对于“动作”,我从我的 .dll 调用我的函数,该函数发出许多 HTTP 请求并将响应作为文件写入应用程序安装文件夹。这不是 CPU 密集型的,但可能需要几秒钟。或者,如果互联网连接较弱/没有可用的互联网连接,则可能需要一两分钟。并且安装程序 GUI 一直被冻结。

4

2 回答 2

6

输出进度页面旨在提供对较长运行操作的反馈。

但是为了使这有效,您必须能够通过定期调用此页面上的方法来让 Inno 更新您当前的进度。

有一个库可以让您将 Inno 脚本函数作为回调传递给 DLL,这可能有用。您可能还想查看使用来自同一站点的 ITDownload 脚本,它允许您从 Inno 内部进行 HTTP 访问,避免中间人。

然而 Inno 本质上是单线程和 GUI-thread-affine 的,所以直接调用阻塞操作总是会阻塞 UI 而没有特殊的规定。可以在单独的线程中运行代码(但只能在 DLL 中,您必须非常小心);其他选项包括仅进行异步调用,或内部维护 GUI 更新的调用,例如Exec.

于 2013-01-18T10:17:33.393 回答
3

有两种方法可以改善体验(它们仅从 API 的角度来看不同,在内部两者都做同样的事情——它们泵送 Windows 消息队列):

  1. 用于TOutputProgressWizardPage呈现操作进度。它的SetProgress方法在内部调用 VCL TApplication.ProcessMessages,它会抽取 Windows 消息队列。

    用于CreateOutputProgressPage创建页面。

    一些例子:

  2. 通过调用 WinAPI 显式抽取 Windows 消息队列DispatchMessage

    有关一些示例,请参见以下AppProcessMessage功能:


在这两种情况下,您都必须添加触发消息队列抽取的调用。通常在进行处理的某个循环内。

在某些情况下,您将无法做到这一点。例如,当您使用对外部应用程序的阻塞调用(例如使用Execor ShellExec)进行处理时。您可以通过安排在函数运行时定期触发的计时器来解决此问题。

上面链接的一些示例使用了这种方法,即:

于 2017-07-13T04:36:19.503 回答