I'm using TJclZipCompressArchive from the Jedi JCL with the 7zip.dll to add multiple files to a ZIP archive like this:
arch := TJclZipCompressArchive.Create(_ZipFn);
arch.OnProgress := HandleOnProgress;
for i := 0 to Files.Count - 1 do begin
fn := Files[i];
arch.AddFile(ExtractFileName(fn), fn);
end;
arch.Compress;
arch.CheckOperationSuccess;
(This code is called in the main VCL thread.) While this works, I have a problem showing the progress and optionally allowing the user to abort the operation. For that purpose I have added an OnProgress handler:
procedure Tf_ZipMeasurement.HandleOnProgress(Sender: TObject; const Value, MaxValue: Int64);
begin
// originally this called Application.ProcessMessages
TThread.Synchronize(nil, SyncHandleProgress);
if FAborted then
TJclZipCompressArchive(Sender).CancelCurrentOperation := True;
end;
Originally, I simply updated the user interface and called Application.ProcessMessages. This didn't work, because the thread calling this event isn't the main VCL thread, so I changed it to call TThread.Synchronize instead.
Unfortunately this results in a deadlock, because apparently the main thread is busy doing something within the 7zip.dll. (Since the documentation on TJclZipCompressArchive is nonexistent, I'm guessing here.)
As far as I see it, in order to get this to work, I would have to call arch.Compress in a background thread, so the main thread is available to do message handling.
Does anybody have some experience with using TJclZipCompressArchive or the 7zip.dll? Is the right way to do it? Or is there a better / simpler option?
Your analysis is correct. If the ZIP library calls your progress event handler on a different thread, then calling Synchronize
from that thread is a deadlock. You said:
apparently the main thread is busy doing something within the 7zip.dll
Well, what it is doing is what you told it to do! Namely to compress the archive. Since the ZIP library is not native to Delphi, it is not going to dispatch Synchronize
requests.
The way forward is to call Compress
from a worker thread.