I've just added threading to an application using Delphi's TThread Class. The thread calls a function which compares two files and print the bits that are different between them. Before I introduced threading the application could complete this procedure and print the output in about 1 - 2 seconds on a 300KB file. After introduction of threading checking the same file can take up to 30 - 45 seconds and cause a 50% CPU spike (AMD Phenom II Triple Core), previously you didn't notice a spike.
The code that is being executed by the thread is:
procedure TForm1.CompareFiles(fil1, fil2 : ansistring; sg : TStringGrid; option : integer; progb : TProgressBar);
var
forg, fpat : file;
byteorg, bytepat : Byte;
byteorgc,bytepatc : ansistring;
arrby : Array Of ansistring;
arrpos : Array Of ansistring;
i,x : integer;
begin
if CRCAdlerGenFile(fil1,1) <> CRCAdlerGenFile(fil2,1) then //Only Run if files arn't same
begin
sg.Cols[0].Clear;
sg.Cols[1].Clear;
i := 0;
x := 0;
AssignFile(forg,fil1);
FileMode := fmOpenRead;
Reset(forg,1);
AssignFile(fpat,fil2);
FileMode := fmOpenRead;
Reset(fpat,1);
//Set Progress Bar
progb.Min := 0;
progb.Max := FileSize(forg);
while NOT eof(forg) do
begin
BlockRead(forg,byteorg,1);
BlockRead(fpat,bytepat,1);
Progb.Position := Progb.Position + 1;
byteorgc := IntToHex(byteorg,2);
bytepatc := IntToHex(bytepat,2);
if byteorg <> bytepat then
begin
x := x + 1;
SetLength(arrby,x);
SetLength(arrpos,x);
arrpos[i] := IntToStr(FilePos(forg));
arrby[i] := bytepatc;
i := i + 1;
end;
end;
CloseFile(forg);
CloseFile(fpat);
case option of
0 : begin //Base 2
for I := 0 to (Length(arrpos) - 1) do
begin
arrpos[i] := IntToBin(StrToInt(arrpos[i]),8);
end;
end;
1 : ; //Base 10
2 : begin //Base 16
for I := 0 to (Length(arrpos) - 1) do
begin
arrpos[i] := IntToHex(StrToInt(arrpos[i]),1);
end;
end;
3 : begin //Append $
for I := 0 to (Length(arrpos) - 1) do
begin
arrpos[i] := '$'+IntToHex(StrToInt(arrpos[i]),1);
end;
end;
4 : begin //Append 0x
for I := 0 to (Length(arrpos) - 1) do
begin
arrpos[i] := '0x'+IntToHex(StrToInt(arrpos[i]),1);
end;
end;
end;
Sg.RowCount := Length(arrpos);
for I := 0 to (Length(arrpos) - 1) do
begin
sg.Cells[0,i] := arrpos[i];
sg.Cells[1,i] := arrby[i];
end;
if sg.RowCount >= 16 then
sg.DefaultColWidth := 222
else
sg.DefaultColWidth := 231;
end;
end;
The threading code used was pretty much taken from this previous question I asked with slight name changes and the introduction and a progress bar variable, however that was added after I noticed the slow processing as a way for me to monitor it.
Link to previous question for threading code.
UPDATE:
Fixed Code Looks something like this. I have totally remove the function CompareFiles and moved the code into Thread.Execute for ease of read/usage.
procedure TCompareFilesThread.Execute;
var
forg, fpat : file;
byteorg, bytepat : Array[0..1023] of byte;
i,z,o : integer;
fil1,fil2 : TFilename;
begin
//Form1.CompareFiles(FEdit3Text, FEdit4Text, FGrid, FOp, FProg);
begin
fil1 := Form1.Edit3.Text;
fil2 := Form1.Edit4.Text;
if Form1.CRCAdlerGenFile(fil1,1) <> Form1.CRCAdlerGenFile(fil2,1) then //Only Run if files arn't same
begin
i := 0;
x := 1;
o := 0;
AssignFile(forg,fil1);
FileMode := fmOpenRead;
Reset(forg,1);
AssignFile(fpat,fil2);
FileMode := fmOpenRead;
Reset(fpat,1);
//Set Progress Bar
while NOT eof(forg) do
begin
while Terminated = False do
begin
BlockRead(forg,byteorg,1024);
BlockRead(fpat,bytepat,1024);
for z := 0 to 1023 do
begin
if byteorg[z] <> bytepat[z] then
begin
synchronize(sProgBarNext);
by := bytepat[z];
off := IntToStr(o);
synchronize(SyncGrid);
inc(x);
end;
inc(o);
end;
end;
end;
CloseFile(forg);
CloseFile(fpat);
end;
end;
Free;
end;
Sync Grid
procedure TCompareFilesThread.SyncGrid;
begin
form1.StringGrid2.RowCount := x;
if x >= 16 then
form1.StringGrid2.DefaultColWidth := 222
else
Form1.StringGrid2.DefaultColWidth := 232;
case op of
0 : off := IntToBin(StrToInt(off),8); //Base 2
1 : ; //Base 10
2 : off := IntToHex(StrToInt(off),1);//Base 16
3 : off := '$'+IntToHex(StrToInt(off),1); //Append $
4 : off := '0x'+IntToHex(StrToInt(off),1);//Append 0x
end;
form1.StringGrid2.Cells[0,(x-1)] := off;
form1.StringGrid2.Cells[1,(x-1)] := IntToHex(by,2);
end;
Sync Prog
procedure TCompareFilesThread.SProgBarNext;
begin
Form1.ProgressBar1.Position := Form1.ProgressBar1.Position + 1;
end;