在不锁定应用程序的情况下将详细信息输出到备忘录的最佳方法是什么

What is the best way to output verbose to a memo without locking down the application

我正在开发一个基于 Delphi 10 Seattle 的应用程序,该应用程序使用 FireDAC 的工具集执行多项任务以执行备份,在 Firebird 数据库上恢复和维护例程。

此工具集中包含的组件(TFDIBBackup、TFDIBRestore 和 TFDIBValidade)都具有 Verbose 选项,可让您拦截输出并能够将其输出到某个地方以便阅读。

我正在尝试将其输出到备忘录中,但遇到了一些问题。

主要问题是:数据库越大,进程明显变慢,输出的行越多,这与备份/恢复数据库所需的时间直接相关。如果您完全禁用冗长,则该过程所花费的时间会下降到大约总时间的 10%。太疯狂了。

在我的实验中,我发现如果我使用另一个线程将详细信息输出到备忘录,这个过程不会对性能造成太大影响,就像非详细选项的 90%,这很棒。但是我 运行 遇到了一个问题,使用线程会使应用程序创建某种线程堆栈,最终将输出到备忘录中,但问题是进程本身已经完成并且行将保留一直输出到备忘录

如果我不使用线程来执行此操作,则进程的性能会受到很大影响,并且应用程序基本上会被锁定,直到进程完成。

有谁知道在不锁定 UI 或导致我上面解释的问题的情况下输出此工具集的详细信息的任何好方法?

我决定实施 AmigoJack 的建议,即使用 AllocConsole()Writeln() 来显示 Firebird 的详细输出。它运行良好,不会锁定我的应用程序的 GUI。

要防止用户在关闭控制台时关闭应用程序,您可以获取该控制台的句柄,然后删除关闭按钮。

您需要先声明此函数:

function GetConsoleWindow: HWND; stdcall; external kernel32;

这是分配新控制台然后隐藏按钮的代码:

var
  handle: HWND;
  consoleMenuItem: HMENU;
begin
  AllocConsole();

  handle := GetConsoleWindow;

  if IsWindow(handle) then
  begin
    consoleMenuItem := GetSystemMenu(Handle, False);

    if IsMenu(consoleMenuItem) then
    begin
      DeleteMenu(consoleMenuItem, SC_CLOSE, MF_BYCOMMAND);
    end;
  end;
end;

只要记得添加一种方式让用户调用 FreeConsole() 以便在您不再需要控制台时摆脱它,或者您自己调用它。