[Lazarus] custom thread reading file does not respond properly
Andrea Mauri
andrea.mauri.75 at gmail.com
Wed Sep 6 18:15:24 CEST 2017
> Note that his example works on my Mac with or without
> sleep. Maybe if Andrea posts his full example we may find out more.
>
> Mattias
>
Unfortunately I cannot post the real case, it is included in a bigger
unit involving other stuffs.
Anyway the example I posted is quite the same.
In order to better clarify my issue:
- I have to manage text files including some logical blocks (items),
these files can be huge (gigabytes) and they can store millions of items
(some file types define an item using a single line). My application
deals with these files enabling the user to visualize the items in a
grid and rapidly move along the file.
I encounter it in two different threads:
1. a thread that I launch when the user load one of these files. This
thread simply reads the file, counts the items and stores the position
of the items (streambuffer positions).
2. a thread reading a file and looking for a substring.
1. source
procedure TCountItemsThread.Execute;
var
streamreader: TStreamReader;
streampos, streamsize: Int64;
bufferpos, nitems: Integer;
begin
_itemfile:= TItemsFile.Create(_filename, _fileformat);
try
streamreader:= _itemfile._streamreader;
streamreader.Reset;
streamsize:= streamreader.BaseStream.Size;
_itempos.Clear;
_itembufpos.Clear;
nitems:= 0;
while not Terminated and not streamreader.Eof do
begin
// stores items source position in file as Position and
BufferPosition
streampos:= streamreader.Position;
if streamreader.BufferRead < (BUFFER_SIZE - 1) then
streampos:= streampos - (streamreader.BufferRead)
else
streampos:= streampos - (BUFFER_SIZE - 1);
bufferpos:= streamreader.BufferPosition;
if (bufferpos = 0) and (streampos > 0 ) then
begin
streampos:= streampos - (BUFFER_SIZE - 1);
bufferpos:= BUFFER_SIZE - 1;
end;
if _itemsfile.nextItem then begin
_itempos.Add(streampos);
_itembufpos.Add(bufferpos);
_progress:= round((streampos / streamsize) * 100);
Inc(nitems);
if (_itempos.Count mod 1000) = 0 then begin
Synchronize(@CountingItems);
end;
end;
end;
Synchronize(@EndCountItems);
finally
_itemfile.Free;
end;
end;
nextItem simply parse the file and move the stream to the next item
position. If the file has single line items I cannot interact with my
app even on win.
2. source
procedure TFilterNameThread.Execute;
var
substr, str1: string;
i, step, occurrences: Integer;
clonedfile: TItemFile;
begin
// if substr is empty do not perform search
FFindItems.Size:= FItemFile.CountItems;
if Trim(FindString) = '' then begin
for i:= 0 to FItemFile.CountItems - 1 do begin
FFindItems[i]:= True;
end;
_itemidx:= FItemFile.CountItems;
Synchronize(@ShowProgress);
Exit;
end;
// store original FItemFile.Selected[] and sets FItemFile.Selected[]
to False
_itemidx:= 0;
FFindItems.Clearall;
Synchronize(@ShowProgress);
clonedfile:= FItemFile.CloneFile;
try
step:= clonedfile.CountItems div 100;
if step = 0 then
step:= 1;
substr:= FindString;
if not CaseSensitive then
substr:= upcase(substr);
occurrences:= 0;
while (not Terminated) and (_itemidx < clonedfile.CountItems) do begin
if CheckAll or Selected[_itemidx] then
begin
str1:= clonedfile.ItemName[_itemidx];
if not CaseSensitive then
str1:= upcase(str1);
if Pos(substr, str1) > 0 then begin
FFindItems[_itemidx]:= True;
Synchronize(@ShowProgress);
Inc(occurrences);
end;
end;
if (_itemidx mod step) = (step - 1) then begin
Sleep(5);
Synchronize(@ShowProgress);
end;
Inc(_itemidx);
end;
Synchronize(@ShowProgress);
finally
clonedfile.Free;
end;
end;
More information about the Lazarus
mailing list