如何让主(调用)线程等待子线程完成执行?

How to make the main (calling) thread wait for a child thread to complete execution?

使用:Delphi 10 Seattle,Win32 VCL 表单应用程序

我正在开发一个更新程序,用于检查一个或多个已安装软件应用程序的更新,并在找到更新时按顺序下载更新。下载每个更新后,它将在继续下载下一个更新之前安装更新。下载位实现为线程class(TThread 的后代),其构造函数如下:

constructor TWebFileDownloaderThread.Create(CreateSuspended: Boolean; const AWebFileURL, ALocalFilePath: String;
  ACallBackProc: TProgressCallback; AProxySetting: TProxySetting);
begin
  inherited Create(CreateSuspended);

  FWorkResult := False;

  FWebFileURL := AWebFileURL;
  FProxySetting := AProxySetting;
  FLocalFilePath := ALocalFilePath;

  FUpdateCallbackProc := ACallBackProc;
end;

主线程创建并启动下载线程如下:

procedure TfmMain.DownloadUpdateFromWeb(const AInstallerFileURL: String);
var
  internet_file_download_thread: TWebFileDownloaderThread;
begin
  internet_file_download_thread := TWebFileDownloaderThread.Create(True, AInstallerFileURL, FUpdateDownloadDir,
    UpdateProgressCallback, FProxySetting);

  internet_file_download_thread.OnTerminate := WebFileDownloaderThread_TerminatedMethod;
  internet_file_download_thread.FreeOnTerminate := True;
  internet_file_download_thread.Start;
end;

我的具体问题是:如何让主(调用)UI 线程等到下载线程完成,然后再创建新的下载线程开始下一次下载?

我认为需要某种形式的排队,但不确定如何实施。非常感谢您的提示和建议。

你不应该阻塞主线程。所以不要等到工作线程完成。而是安排工作线程在完成时向主线程发出信号。例如:

  • 正在发送消息,或
  • 使用TThread.Synchronize,或
  • 使用TThread.Queue,或
  • 处理线程的OnTerminate事件,或
  • 一些其他形式的 inter-thread 交流。

OnTerminate 对我来说是个不错的选择。

您也可以考虑使用更高级别的并行库。例如 RTL 的并行库或 OTL。这样你就可以避免纠结于线程的细节,让并行库来处理这些事情。

如果您这样做,您可以使用 producer/consumer 架构设计您的应用程序:

  1. 创建线程安全队列。
  2. 创建一个或多个下载线程,这些是消费者。
  3. 主线程,即生产者,将下载作业推送到队列中。
  4. 消费者线程在队列上等待,当它包含作业时,消费者线程通过下载文件来完成作业并处理它们。

这种设计使用高级并行库实现起来非常简单。

如果我没理解错的话,您有一个 URL 列表可供下载和安装(通过先前执行更新检查获得)。您想从这些 URL 下载更新并一一安装:下载更新 1、安装更新 1、下载更新 2、安装更新 2,等等

这是一个可能的设计:

在您的 WebFileDownloaderThread_TerminatedMethod 中,开始安装刚刚下载的更新(要保持主线程响应,请在单独的线程中执行此操作)。

在安装程序线程的OnTerminate处理程序中,删除刚刚完成的URL(或将其标记为已处理)并开始下载下一个,再次调用DownloadUpdateFromWeb,除非列表已经为空(或不再包含未处理的项目)。

(顺便说一句,方法 DownloadUpdateFromWeb 最好命名为类似 BeginDownloadUpdateFromWeb 的名称,以表明其异步性质。)