Witam!
Od dwóch dni próbuje pojąć dlaczego mój program w losowych momentach przestaje działać.
Opis działania kodu.
Wątek SupervisorThread przygotowuje listę plików do połączenia w ChunksToCombineList (TStringList). Nowe wpisy są oczywiście dodawane w kotekście głównego wątku (Synchronize()).
Po dodaniu nowej pozycji w ChunksToCombineList wznawiany jest uśpiony wątek CombineChunksThread.
procedure TSupervisorThread.Execute;
begin
while Terminated=false do
begin
Synchronize(UpdateListOfChunksToCombine);
sleep(250);
end;
end;
procedure TSupervisorThread.UpdateListOfChunksToCombine;
begin
while NextChunkToCombineIndex<form1.JvListView1.Items.Count do
begin
if Pos('encoded',form1.JvListView1.Items.Item[NextChunkToCombineIndex].SubItems.Strings[1])<>0 then
begin
ChunksToCombineList.Add(IntToStr(NextChunkToCombineIndex+1));
if (Assigned(CombineChunksThread)=true) and (CombineChunksThread.Suspended=true) then CombineChunksThread.Resume;
Inc(NextChunkToCombineIndex);
end
else break;
end;
end;
procedure TCombineChunksThread.Execute;
begin
repeat
Synchronize(CheckChunksToCombine);
if (ChunkToCombine<>'') and (CombineChunk(ChunkToCombine)=true) then Inc(NumberOfCombinedChunks);
until (Terminated=true) or (NumberOfCombinedChunks=NumberOfChunksToCombine);
end;
procedure TCombineChunksThread.CheckChunksToCombine;
begin
if ChunksToCombineList.Count>0 then
begin
ChunkToCombine:=ChunksToCombineList.Strings[0];
ChunksToCombineList.Delete(0);
end
else
begin
ChunkToCombine:='';
Suspend;
end;
end;
function TCombineChunksThread.CombineChunk(ChunkIndex:string):boolean;
var OutputFile,InputFile:string;
BytesRead, BytesWritten: Integer;
DataArray: array of byte;
FlagsAndAttributes: DWORD;
SourceFileHandle,TargetFileHandle: THandle;
SourceStream,TargetStream: TFileStream;
SumOfBytesRead,SumOfBytesWritten,SourceFileSize,TargetFileSize:int64;
BufferSize:integer;
function ReturnFileSize(const FileName: string):Int64;
var SearchRec : TSearchRec;
begin
if FindFirst(FileName,faAnyFile,SearchRec)=0 then Result:=Int64(SearchRec.FindData.nFileSizeHigh) shl Int64(32)+Int64(SearchREc.FindData.nFileSizeLow)
else Result:=0;
FindClose(SearchRec);
end;
begin
Result:=false;
InputFile:=FolderWithChunks+'\'+ChunkIndex+codec_extension;
OutputFile:=VideoPartFile;
FlagsAndAttributes:=FILE_ATTRIBUTE_NORMAL;
SourceFileHandle:=CreateFile(PChar(InputFile), GENERIC_READ, FILE_SHARE_READ, nil,OPEN_ALWAYS, FlagsAndAttributes, 0);
TargetFileHandle:=CreateFile(PChar(OutputFile), GENERIC_WRITE, FILE_SHARE_WRITE, nil,OPEN_ALWAYS, FlagsAndAttributes, 0);
if SourceFileHandle=INVALID_HANDLE_VALUE then exit;
SourceFileSize:=ReturnFileSize(InputFile);
TargetFileSize:=ReturnFileSize(OutputFile);
SourceStream:=TFileStream.Create(SourceFileHandle);
TargetStream:=TFileStream.Create(TargetFileHandle);
BufferSize:=16777216; //16 MiB
SetLength(DataArray,BufferSize);
SumOfBytesRead:=0;
SumOfBytesWritten:=0;
try
TargetStream.Position:=TargetFileSize;
repeat
BytesRead:=SourceStream.Read(DataArray[0],BufferSize);
SumOfBytesRead:=SumOfBytesRead+BytesRead;
BytesWritten:=TargetStream.Write(DataArray[0],BytesRead);
SumOfBytesWritten:=SumOfBytesWritten+BytesWritten;
until (BytesRead=0) or (BytesWritten=0) or (BytesRead<>BytesWritten) or (Terminated=true);
finally
SourceStream.Free;
TargetStream.Free;
CloseHandle(SourceFileHandle);
CloseHandle(TargetFileHandle);
if SumOfBytesWritten=SourceFileSize then Result:=true;
end;
end;
Parę godzin temu odkryłem że powodem zawieszania jest zwalnianie pamięci w funkcji CombineChunk. Gdy usunę te dwie linijki to program się nie zwiesza i wszystko działa jak należy.
SourceStream.Free; //lub FreeAndNil(SourceStream)
TargetStream.Free; //lub FreeAndNil(TargetStream)
Może ktoś mi to wytłumaczyć dlaczego sprzątanie po sobie powoduje takie anomalie?
Ps. Używam Delphi7 oraz Windows7 x64 SP1 + najnowsze aktualizacje