I need to log some data and preferrably copy files using a thread, but by using the code below, but it simply freezes my app.
if I understand the whole XE7 Parallell library correctly TThread.Queue
and TThread.Synchronize
are supposed to sync with the main thread, but in my case the whole app freezes.
What am I doing wrong?
procedure TCopyDeviceContent.StartCopy;
var
OK: boolean;
begin
OK := false;
// showmessage('fFiles.Count = '+inttostr(fFiles.Count));
if fFiles.Count = 0 then
begin
NotifyDone;
exit;
end;
TParallel.For(0, fFiles.Count-1,
procedure (Value: Integer)
begin
TThread.Queue(TThread.CurrentThread, //Here is where it freezes
procedure
begin
Log('Setting fCurrentFile to '+fFiles.Strings[value]);
end
);
sleep(1000);
fCurrentFile := fFiles.Strings[value];
Log('Triggering fOnBeforeProcess');
if assigned(fOnBeforeProcess) then fOnBeforeProcess(self);
Log('Does file exist?');
if FileExists(fFiles.Strings[value]) = true then
begin
Log('Yes!');
Log('Trying to copy file to Windows temp folder.');
try
TFile.Copy(fFiles.Strings[value], GetEnvironmentVariable('TEMP'));
finally
OK := true;
end;
if OK = true then
begin
Log('Success!');
OK := false;
Log('Does file exist in Windows temp folder?');
if FileExists(GetEnvironmentVariable('TEMP')+ExtractFileName(fFiles.Strings[value])) then
begin
Log('Yes');
Log('Trying to copy file from Windows temp folder to final destination: '+DestPath+DateToStr(Now)+'\'+ExtractFileName(fFiles.Strings[value]));
try
TFile.Move(GetEnvironmentVariable('TEMP')+ExtractFileName(fFiles.Strings[value]),
DestPath+DateToStr(Now)+'\'+ExtractFileName(fFiles.Strings[value]));
finally
fFilesOK.Add(fFiles.Strings[value]);
Log('Sucess!');
end;
end;
end
else
begin
fFilesFailed.Add(fFiles.Strings[value]);
Log('Failed copying to Windows temp folder!');
end;
end;
inc(fProgress);
NotifyProgress;
Log('File copy success. Moving on to next file if available...');
end
);
NotifyDone;
if fFilesFailed.Count > 0 then NotifyError;
end;
If goal is just to copy files without freezing UI thread i would just use something like this:
procedure TCopyDeviceContent.StartCopy;
var
aTask: ITask;
begin
aTask := TTask.Create (procedure ()
begin
// Copy files here
TThread.Synchronize(nil,procedure
begin
//Interact with UI
Form1.Memo1.Lines.Add(‘Begin Execution’);
end);
end);
aTask.Start;
end;
Inside task procedure just copy files as you would do it usually, i am not sure if copying using multiple threads will help you.
In case you need interact with UI you need to switch back to UI thread, you can use TThread.Synchronize.