使用: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线程等到下载程序线程完成,然后?
我认为需要某种形式的排队,但不确定如何实现它。非常感谢您的提示和建议。
答案 0 :(得分:3)
你不应该阻止主线程。所以不要等到工作线程完成。而是安排工作线程在完成后向主线程发出信号。例如:
TThread.Synchronize
或TThread.Queue
或OnTerminate
事件,或 OnTerminate
看起来对我来说是个不错的选择。
您也可以考虑使用更高级别的并行库。例如RTL的并行库或OTL。这样你就可以避免纠缠于线程的细节,并让并行库处理这些问题。
如果您这样做,您可以使用生产者/消费者架构设计您的应用程序:
使用高级并行库实现这种设计非常简单。
答案 1 :(得分:3)
如果我理解正确,您有一个要下载和安装的URL列表(通过先前执行更新检查获得)。您想从这些URL下载更新并逐个安装:下载更新1,安装更新1,下载更新2,安装更新2等。
这是一个可能的设计:
在WebFileDownloaderThread_TerminatedMethod
中,开始安装刚下载的更新(为了保持主线程的响应,请在单独的线程中执行此操作)。
在安装程序线程的OnTerminate
处理程序中,删除刚刚完成的URL(或将其标记为已处理)并再次调用DownloadUpdateFromWeb
开始下载下一个URL,除非该列表已为空(或不包含任何未处理的项目)。
(顺便说一句,方法DownloadUpdateFromWeb
最好用BeginDownloadUpdateFromWeb
命名,以表明其异步性质。)