![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Поток не выполняет Execute без WaitFor. Что не так? (+) [D7, WinXP]
EarlVadim © (2006-01-24 19:47:00)Если при вызове потока стоит WaitFor - то всё работает, но программа ждёт выполнения потока и смысл его (потока) теряется. Мы тупо сидим и ничего в проге не можем делать.
Если снять WaitFor, то процедура потока EXECUTE - не получает управления. Пробовал самые разные варианты вызова потока - ничего не лечит. Уже понял, что где-то что-то не так В ПРИНЦИПЕ. Подскажите, уже 2 дня убил....
Привожу UNIT целиком......
unit MyThreadU;
interface
uses
Classes, Windows, SysUtils;
type
MyThread = class(TThread)
private
CF : array of String;
FOutPar : array of String;
FReady : array of boolean;
ST : TStrings;
Lens : integer;
protected
procedure Execute; override;
public
constructor Create(InPar : array of String);
function GetFReady(Index: Integer): Boolean;
function GetFOutPar(Index: Integer): String;
property OutPar[Index: Integer] : String Read GetFOutPar;
property Ready[Index: Integer]: Boolean Read GetFReady;
end;
implementation
constructor MyThread.Create(InPar : array of String);
Var
i : integer;
begin
Lens:= Length(InPar);
SetLength(CF,Lens);
SetLength(FReady,Lens);
SetLength(FOutPar,Lens);
For i:= 0 to Lens-1 do begin
CF[i]:= InPar[i];
FReady[i]:= false;
end;
// скопировали входной массив строк
inherited Create(false);
// после этого Execute не выполняется
end;
function MyThread.GetFReady(Index: Integer): boolean;
begin
If Index <= Lens-1 then Result:= FReady[Index];
end;
function MyThread.GetFOutPar(Index: Integer): string;
begin
If Index <= Lens-1 then Result:= FOutPar[Index];
end;
procedure MyThread.Execute;
Var
i : integer;
begin
For i:= 0 to Lens-1 do begin
st:= TStringList.Create;
try
If FileExists(PChar(CF[i])+'\unitinfo.txt') then begin
st.LoadFromFile(PChar(CF[i])+'\unitinfo.txt');
FOutPar[i]:= ST.Strings[1];
end else FOutPar[i]:= '';
finally
FReady[i]:= true;
st.free;
end;
end;
end;
end.
Теперь в программе
Var
HostPath : array of string
Procedure TMainForm.ReadData(Sender: TObject);
Thread := MyThread.Create(HostPath); // список хостов
//прочитан из ini ранее
Thread.Priority := tpLowest;
Thread.FreeOnTerminate := false;
// Thread.WaitFor; {без WaitFor - не работает, а с ним - примораживает. }
For i:= 0 to Hosts-1 do begin
Labels[i].Caption:= Thread.OutPar[i];
end;
Thread.Destroy;
end;
EarlVadim (2006-01-25 12:38:00) [1]begin...end © (24.01.06 20:29) [1]
Да, все верно. Спасибо.
> 1. А так ли уж тут нужен поток ?
Однозначно нужен. Представь цикл из нескольких десятков сетевых файлов.. А в один поток программа "жить" несколько минут будет оч-ч-чень плохо.
Но флаг для ожидания у меня как-раз предусмотрен FReady.
В общем заработало все... спасибо.
ANB (2006-01-24 22:33:00) [2]1. А так ли уж тут нужен поток ? Может Application.ProcessMessages после каждой итерации попроще будет ?
2. Если уж сильно хотите поток, то перед его уничтожением все равно придется ждать, пока он завершится. WaitFor остановит основной поток, так что лучше ждать в цикле какого нибудь флага, выдавая в нем же Application.ProcessMessages, чтобы основной поток "жил".
begin...end (2006-01-24 20:29:00) [3]> EarlVadim © (24.01.06 19:47)
> Thread := MyThread.Create(HostPath);
> ...
> Thread.Destroy; <-- !!!
Создаём экземпляр класса MyThread. В параллельном потоке начинает работать поточная функция (которая и должна, по идее, исполнять код метода Execute). Тем временем, в основном потоке ВЫЗЫВАЕТСЯ DESTROY , который первым делом устанавливает флаг Terminate в True. В параллельном потоке только что запущенная поточная функция обнаруживает, что флаг Terminated уже выставлен, и просто не приступает к исполнению метода Execute.