Спасибо.
Кажется почти разобрался
Код:
.....
For I := Low(FThreads) To High(FThreads) Do
Begin
FThreads[i].Terminate;
FThreads[i].WaitFor;
End;
У TThread есть некое Boolean свойство, при запуске потока оно установлено в False, в обычном случае по завершении Execute оно устанавливается в True и поток самовыпиливается (при FreeOnTerminate:=True разумеется) ... во! нашел
Код:
procedure TThread.Terminate;
begin
...
FTerminated := True;
....
end;
В нашем случае мы зацикливаем Execute с помощью Terminated на проверку очереди заданий, а с помощью FThreads[i].Terminate даем возможность выскочить из цикла и завершить Execute. WaitFor - ждем от потока сообщения: "Я кончил, прощайте". Вроде так.
Только надо придумать как передавать задания не строкой, а ну скажем record, или в качестве задания формировать строку с разделителями, а для потока наколхозить функцию, которая эту строку будет разбирать.
...upd...
Вроде бы остановился на варианте запихать в TList record-ы, а теперь меня терзают смутные сомнения, не ересь ли я написал
пишу по памяти, сам проект остался на работе, в ноуте
Код:
unit MyThread;
...
type
TSomeData = record
n1, n2, n3: Integer;
m1, m2: Byte;
....
Код:
unit Unit1
...
procedur AddToQueue;
var SomeData: TSomeData;
i: Integer;
begin
for i:= 0 to someNamber do
begin
SomeData.n1:= //bla bla bla
SomeData.n2:= //bla bla bla
....
SomeData.m2:= //bla bla bla
List.Add(SomeData);
end;
end;
но TList это список указателей, а я ведь не создаю новый экземпляр TSomeData т.е. я добавляю в лист указатель на одну и ту же переменную.
Но даже если этот вопрос будет решен остается другой
Изначально планировал наследовать от TThread, скажем так прототип, в который инкапсулирую IdHTTP и прочее, а от него создаю наследников под разные задачи с разными, соответственно наборами данных т.е. с разными record-ами (TSomeData1 = record, TSomeData2 = record и т.д.)
В новом варианте усмотрел следующую возможность - ограничится одним наследником, а разные задачи раскидать по разным процедурам
Код:
type
TWorkerThread = class(TThread)
......
FMode: TMode
......
end;
..........
implementation
procedure TWorkerThread.Execute;
var
S : String; //вот тут и загвоздка, я заранее не знаю какой из типов у меня будет в листе
begin
While not Terminated Do
Begin
S := '';
cs.Enter;
Try
If FList.Count > 0 Then
Begin
S := FList[0];
FList.Delete(0);
End;
Finally
cs.Leave;
End;
If S <> ''
Then
Case of FMode
mdCheck: ProcessCheck(S);
mdLoad: ProcessLoad(S);
end;
Else Sleep(1000)
End;
end;
Вернее так - у меня есть FMode и какой тип записи будет я знаю, но это будет уже в RunTime, а объявить переменную нужно сразу.
Я так себе представляю - это нужно из List-а вытащить указатель, независимо от того на какой тип записи он указывает, а в соответствующей процедуре будет объявлена переменная нужного типа и по указателю получаю нужный record.