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

时间:2016-01-07 08:25:36

标签: multithreading delphi delphi-10-seattle

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

我正在开发一个更新程序应用程序,用于检查一个或多个已安装的软件应用程序的更新,并在找到更新时按顺序下载更新。下载每个更新后,它将安装更新,然后继续下载下一个更新。下载位实现为线程类(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线程等到下载程序线程完成,然后?

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

2 个答案:

答案 0 :(得分:3)

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

  • 发送消息,或
  • 使用TThread.Synchronize
  • 使用TThread.Queue
  • 处理线程的OnTerminate事件,或
  • 其他形式的线程间通信。

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

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

如果您这样做,您可以使用生产者/消费者架构设计您的应用程序:

  1. 创建线程安全队列。
  2. 创建一个或多个下载线程,这些是消费者。
  3. 主线程,即生产者,将下载作业推送到队列中。
  4. 消费者线程在队列上等待,当它包含作业时,消费者线程通过下载文件来拉出作业并处理它们。
  5. 使用高级并行库实现这种设计非常简单。

答案 1 :(得分:3)

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

这是一个可能的设计:

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

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

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