![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Запустить TThread повторно?
Cobalt © (2009-02-21 15:14:00)Есть у меня один поток, который обходит каталоги, считает контрольные суммы файлов.
Но каждый раз после окончания работы приходится пересоздавать объект :-(
Вопрос такой: можно ли после окончания исполнения потока повторно использовать объект TThread ?
Например, запустив его метод Create - будет ли создан новый объект TThread, который повиснет в памяти, или он только отработает свой код, заново запустив WinAPI-ый поток исполняться?
Leonid Troyanovsky (2009-02-23 17:01:00) [1]
> Игорь Шевченко © (23.02.09 14:41) [90]
> "Вот из-за этого у нас в стране и бардак
Суров, брат :)
--
Regards, LVT.
Игорь Шевченко (2009-02-23 14:41:00) [2]"Вот из-за этого у нас в стране и бардак, что всякие вроде вас создают индексы по пяти полям" (с) sql.ru
DVM (2009-02-23 12:11:00) [3]
> Вызов как метода, т.е. T.Create(..), выполнит повторную
> инициализацию
> объекта и запуск потока.
Не надо так делать, несмотря на то, что возможно, будут утечки ресурсов, закончится все плохо. Тем более в данной конкретной задаче.
> Cobalt © (21.02.09 18:18) [6]
>
> > DVM © (21.02.09 17:28) [5]
> Так еще ж нужно знать, что он обошел всё, и всё подсчитал.
>
Ну и как это связано? Посчитал - уведомил кого надо, например главный поток, например сообщением и пошел себе считать дальше, или не пошел, а заснул до уведомления.
Leonid Troyanovsky (2009-02-23 08:59:00) [4]
> тимохов (22.02.09 18:23) [87]
> > тот же самый FTerminated.
> да вроде не в констукторе поля то обнуляются, а в прологе
> конструктора
Да, здесь я погнал, ничего не обнуляется, sorry.
Т.е., если был Terminate, то FTerminated и останется true.
А с учетом [86] конструктор должен выглядеть примерно так:
constructor TMyThread.Create;
begin
PBoolean(@Terminated)^ := False;
if Handle <> 0 then
CloseHandle(Handle);
inherited;
end;
--
Regards, LVT.
тимохов (2009-02-22 18:23:00) [5]
> Leonid Troyanovsky © (22.02.09 10:43) [84]
>
> Раньше, в D3 еще, IMHO, у борландов в конструкторе был пропущен
>
> inherited Create и фокус не проходил потому, что не обнулялись
> поля,
> тот же самый FTerminated.
да вроде не в констукторе поля то обнуляются, а в прологе конструктора, типа NewInstance и InitInstance.
Тын-Дын (2009-02-22 14:07:00) [6]
> Leonid Troyanovsky © (22.02.09 10:43) [84]
>Вызов как метода,
> т.е. T.Create(..), выполнит повторную инициализациюобъекта
> и запуск потока.
При этом
1. будет потерян дескриптор нити (не освобождён) и все выделенные ресурсы, так как деструктор не отработает.
2. будет создана новая нить (а не повторно использоваться существующая).
Хотя автора это вполне может устраивать.
Cobalt (2009-02-22 11:31:00) [7]2 Leonid Troyanovsky © (22.02.09 10:43) [84]
Спасибо, не был знаком с особенностями вызова конструктора у уже созданного объекта., спасибо :)
Leonid Troyanovsky (2009-02-22 10:43:00) [8]
> Cobalt © (21.02.09 15:14)
> Например, запустив его метод Create - будет ли создан новый
> объект TThread, который повиснет в памяти, или он только
> отработает свой код, заново запустив WinAPI-ый поток исполняться?
Вызов как метода, т.е. T.Create(..), выполнит повторную инициализацию
объекта и запуск потока.
Раньше, в D3 еще, IMHO, у борландов в конструкторе был пропущен
inherited Create и фокус не проходил потому, что не обнулялись поля,
тот же самый FTerminated.
--
Regards, LVT.
жж (2009-02-22 10:36:00) [9]В данном случае никакая нить вообще не нужна.
ради доступности кнопки "отмена" городить весь огород - это лишнее.
Если бы задачка была фоновая сама по себе, а пользователь тем временем занимался бы в твоей программе чем то другим - то да, потоки, и все дела
а если он все равно будет сидеть ждать результатов, и максимум что может - отменить процесс, то задача решается вставкой обработок цикла сообщений приложением, и все.
Медвежонок Пятачок (2009-02-22 03:54:00) [10]твой класс- обертка над Thread - это у меня код TForm1
то есть все точно так же укладывается в эту модель.
Тын-Дын (2009-02-22 03:52:00) [11]
> Cobalt © (22.02.09 03:46) [78]
>Т.е. дернул объект - тот запустил
> поток, обновил состояния, типа Terminated, Suspended и т.
> п.
И как часто у тебя такое происходит?
Может проще воспользоваться функцией QueueUserWorkItem?
Тын-Дын (2009-02-22 03:50:00) [12]Ну вобщем-то всё нормально.
За исключением таких моментов:
1. Нет проверки на то, что поток занят выполнением. Отключение кнопок - это несерьёзно.
2. Код не защищён от одновременной попытки запуска нового задания.
Это приведёт к сложноуловимым ошибкам при выполнении в многопоточном приложении. Особенно на многопроцессорном компьютере.
Над этими проблемами ещё придётся поработать тому, кто возьмётся писать таким образом-)
Медвежонок Пятачок (2009-02-22 03:49:00) [13]и что это меняет? в чем суть пробемы-то?
Cobalt (2009-02-22 03:46:00) [14]Блин, я уже потерялся в ваших обсуждениях :)
Поясню, что же я хотел.
А хотел я собственно немногого - использовать именно класс TThread, а не сам поток, поскольку создание потока в моем случае - ничтожнейшая часть всей его работы.
Типа как (условно-сокращенно):
formOnCreate
begin
FThread:=TWorkThread.Create(wkNone);
end;
btnUpdateFullOnClick:
begin
FThread.Run(wkUpdateFull);
UpdateButtonsState;
end;
btnUpdatePartOnClick:
begin
FThread.Run(wkUpdatePart);
UpdateButtonsState;
end;
UpdateButtonsState;
begin
for i:=0 to ActionsCount-1 do
Actions[i].Enabled:=not FThread.IsRunning;
begin
А в методе FThread.Run(wkUpdatePart);:
и т.п.
CreateThread()
Т.е. дернул объект - тот запустил поток, обновил состояния, типа Terminated, Suspended и т.п.
Медвежонок Пятачок (2009-02-22 03:33:00) [15]Теперь юзающий нитку модуль:
procedure TForm1.OnMsg(var AMsg: TMessage);
begin
case AMsg.WParam of
0 : begin
ListBox1.Items.Add('result of work : ' + IntToStr(AMsg.LParam));
Button1.Enabled := True;
Button2.Enabled := True;
AMsg.Result := 0;
end;
end;
end;
var t : TBearPigletThread = nil;
function SomeWork1(AData : Pointer) : integer;
var D:PChar;
begin
D := 'C:\*.*';
PostMessage(THandle(AData),LB_DIR,
DDL_DIRECTORY +
DDL_DRIVES +
DDL_EXCLUSIVE +
DDL_HIDDEN +
DDL_READONLY +
DDL_READWRITE +
DDL_SYSTEM,
Integer(D));
Result := 111;
end;
function SomeWork2(AData : Pointer) : integer;
var D:PChar;
begin
D := 'D:\*.*';
PostMessage(THandle(AData),LB_DIR,
DDL_DIRECTORY +
DDL_DRIVES +
DDL_EXCLUSIVE +
DDL_HIDDEN +
DDL_READONLY +
DDL_READWRITE +
DDL_SYSTEM,
Integer(D));
Result := 333;
end;
//Просим нитку сделать одно дело
procedure TForm1.Button1Click(Sender: TObject);
var aData : PBearPigletData;
begin
Button1.Enabled := False;
New(aData);
aData^.bpd_func := SomeWork1;
aData^.bpd_data := Pointer(ListBox1.Handle);
aData^.bpd_Handle := Handle;
if t = nil then
t := TBearPigletThread.CreateIt(aData)
else
begin
t.SetData(aData);
t.Resume;
end;
end;
//Просим нитку сделать другое дело
procedure TForm1.Button2Click(Sender: TObject);
var aData : PBearPigletData;
begin
Button2.Enabled := False;
New(aData);
aData^.bpd_func := SomeWork2;
aData^.bpd_data := Pointer(ListBox1.Handle);
aData^.bpd_Handle := Handle;
if t = nil then
t := TBearPigletThread.CreateIt(aData)
else
begin
t.SetData(aData);
t.Resume;
end;
end;
Медвежонок Пятачок (2009-02-22 03:31:00) [16]Сначала нитка:
const WM_TEST = WM_USER + 1000;
type
TBearPigletFunc = function(AData : Pointer) : integer;
PBearPigletData = ^TBearPigletData;
TBearPigletData = record
bpd_func : TBearPigletFunc;
bpd_data : Pointer;
bpd_Handle : THandle;
end;
TBearPigletThread = class(TThread)
private
{ Private declarations }
fData : PBearPigletData;
protected
procedure Execute; override;
public
constructor CreateIt(AData : PBearPigletData);
procedure SetData(AData : PBearPigletData);
end;
implementation
constructor TBearPigletThread.CreateIt(AData : PBearPigletData);
begin
inherited Create(True);
fData := AData;
FreeOnTerminate := False;
Resume;
end;
procedure TBearPigletThread.Execute;
begin
while not Terminated do
begin
SendMessage(fData^.bpd_Handle,WM_TEST,0,fData^.bpd_func(fData^.bpd_data));
Dispose(PBearPigletData(fData));
Suspend;
end;
end;
procedure TBearPigletThread.SetData(AData: PBearPigletData);
begin
fData := AData;
end;
Тын-Дын (2009-02-22 02:50:00) [17]Кстати, и с эвентами, и без эвентов реализуется задача тривиально.
Но без эвентов мне твой код хочется увидеть, коль ты уж так здесь много понаписал против них.
Тын-Дын (2009-02-22 02:48:00) [18]
> Медвежонок Пятачок © (22.02.09 02:46) [73]
> ну что тебе показать?пиши. ради праздника покажу.
Я тебе уже написал.
Теперь дело за тобой - код в студию. Реализованный класс. Где так мало кода, где нет дурацких эвентов...
Тын-Дын (2009-02-22 02:46:00) [19]
> у меня один поток в одном экземпляре после первого прогона
> повторно выполняет некторую работу по клику без создания
> нового потока.
У тебя он выполняет не некую работу.
У тебя он выполняет всё тот же дурацкий цикл.
Медвежонок Пятачок (2009-02-22 02:46:00) [20]ну что тебе показать?
пиши. ради праздника покажу.