Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Запустить TThread повторно?


Страницы:   1 2 3 4 5

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]

ну что тебе показать?
пиши. ради праздника покажу.


Страницы:   1 2 3 4 5

Наверх

Титульная страница Поиск, карта сайта Написать письмо