Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.04.12;
Скачать: CL | DM;

Вниз

Запустить TThread повторно?   Найти похожие ветки 

 
Cobalt ©   (2009-02-21 15:14) [0]

Есть у меня один поток, который обходит каталоги, считает контрольные суммы файлов.
Но каждый раз после окончания работы приходится пересоздавать объект :-(

Вопрос такой: можно ли после окончания исполнения потока повторно использовать объект TThread ?

Например, запустив его метод Create - будет ли создан новый объект TThread, который повиснет в памяти, или он только отработает свой код, заново запустив WinAPI-ый поток исполняться?


 
Eraser ©   (2009-02-21 15:19) [1]

> Вопрос такой: можно ли после окончания исполнения потока
> повторно использовать объект TThread ?

можно, и не только после окончания.


 
Cobalt ©   (2009-02-21 15:23) [2]

Хотелось бы видеть нечто вроде
FireThread
проверяя завершение потока по Terminated
не удаляя существующего объекта.


 
Eraser ©   (2009-02-21 15:50) [3]

> [2] Cobalt ©   (21.02.09 15:23)

для этого можно использовать TThread или любой другой класс, вызывая его метод Execute из другого потока, созданного к примеру через BeginThread или тот же TThread.


 
Тын-Дын ©   (2009-02-21 16:56) [4]


> для этого можно использовать TThread или любой другой класс,
>  вызывая его метод Execute из другого потока, созданного
> к примеру через BeginThread или тот же TThread.


Что сказать-то вообще хотел?


> Cobalt ©   (21.02.09 15:14) 



> Вопрос такой: можно ли после окончания исполнения потока
> повторно использовать объект TThread ?


Посмотри простой пример:

type

 TThrProc=procedure;

 TThrTest=class(TThread)
 private
   FThrProc: TThrproc;
   FEvent: THandle;
   FExecEvent: THandle;
 protected
   procedure Execute; override;
 public
   constructor Create;
   destructor Destroy; override;

   function Exec(Proc: TThrProc): Boolean;
   procedure EndThread;
 end;

var
 Thr: TThrTest;

implementation

procedure ProcThr1;
begin
 MessageBox(0,"qqq","qqq",MB_OK);
end;

procedure ProcThr2;
begin
 Sleep(1000);
 MessageBox(0,"sss","sss",MB_OK);
end;

{ TThrTest }

constructor TThrTest.Create;
begin
 inherited Create(True);
 FEvent := CreateEvent(nil,False,False,"");
 FExecEvent := CreateEvent(nil,False,False,"");
 FreeOnTerminate := True;
 Resume;
 WaitForSingleObject(FExecEvent, INFINITE);
 SetEvent(FExecEvent);
end;

destructor TThrTest.Destroy;
begin
 CloseHandle(FEvent);
 CloseHandle(FExecEvent);
 inherited;
end;

procedure TThrTest.Execute;
begin
 SetEvent(FExecEvent);
 while not Terminated do
 begin
   if Terminated then Exit;
   try
     if Assigned(FThrProc) then FThrProc;
     FThrProc := nil;
   except
     //
   end;
   SignalObjectAndWait(FExecEvent,FEvent,INFINITE,False);    
 end;
end;

function TThrTest.Exec(Proc: TThrProc): Boolean;
begin
 Result := False;
 if WaitForSingleObject(FExecEvent,0)=WAIT_OBJECT_0 then
 begin
   Result := True;
   FThrProc := Proc;
   SetEvent(FEvent);
 end;

end;

procedure TThrTest.EndThread;
begin
 Terminate;
 SetEvent(FEvent);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 if not Assigned(Thr) then Thr := TThrTest.Create;
 if not Thr.Exec(@ProcThr1) then ShowMessage("Busy");
 Sleep(2000);
 if not Thr.Exec(@ProcThr2) then ShowMessage("Busy");

end;


 
DVM ©   (2009-02-21 17:28) [5]


> Есть у меня один поток, который обходит каталоги, считает
> контрольные суммы файлов.
> Но каждый раз после окончания работы приходится пересоздавать
> объект :-(
>

А добавить в него бесконечный цикл не судьба? Ну конечно не совсем бесконечный, чтобы возможность завершения была, но не самопроизвольного.
И пусть он себе ходит по каталогам и делает что тебе надо.


 
Cobalt ©   (2009-02-21 18:18) [6]

> DVM ©   (21.02.09 17:28) [5]
Так еще ж нужно знать, что он обошел всё, и всё подсчитал.
И чтобы для этого не добавлять кучу дополнительных полей...


 
Медвежонок Пятачок ©   (2009-02-21 18:42) [7]

в конце execute postmessage наружу и по приемеу resume ему снаружи

либо тупо цикл в сам execute

детские какие-то вопросы.

"повторно использовать"

ломает create что ли вызвать еще раз?


 
Тын-Дын ©   (2009-02-21 20:54) [8]


> детские какие-то вопросы.


Вряд ли ты пытался на них для себя кодом ответить.


 
Медвежонок Пятачок ©   (2009-02-21 21:05) [9]

в чем-то ты прав. я не пытался ответить на них (вопросы) потому что таких вопросов у меня не возникало никогда


 
Медвежонок Пятачок ©   (2009-02-21 21:10) [10]

Посмотри простой пример:

type

TThrProc=procedure; .....


этот пример лучше никому не показывать, а самому втихаря переться от своей крутости.
За какой надобностью здесь потребовалось использовать евенты?


 
Riply ©   (2009-02-21 21:22) [11]

> [0] Cobalt ©   (21.02.09 15:14)
> Вопрос такой: можно ли после окончания исполнения потока повторно использовать объект TThread ?

Например, не выходить из него, а ожидать события или сообщения.

> [7] Медвежонок Пятачок ©   (21.02.09 18:42)
> ломает create что ли вызвать еще раз?

Если бы ты знал, как "ломает", ибо это довольно "тяжелая" для системы операция (создание нити).


 
Медвежонок Пятачок ©   (2009-02-21 21:24) [12]

а евент это конечно очень дешевый для процесса объект


 
Riply ©   (2009-02-21 21:51) [13]

> [12] Медвежонок Пятачок ©   (21.02.09 21:24)
> а евент это конечно очень дешевый для процесса объект

Честно говоря - не знаю степень его (Eventa) "тяжести" :)
Но с нитями неоднократно ставила различные опыты.
Например, были очень старые исходники Rouse`а - перебор открытых файлов.
Там он на каждый запрос создавал нить ( сканирование занимало ~ 30-40 сек )
Я попробовала не уничтожать нить (если нет необходимости, а повторно использовать).
Сканирование стало занимать доли секунды. Разница на порядки :)
Числа по памяти - могу ошибаться (давно это было), но то что разница измерялась порядками - "эт точто" :)
Да ты и сам можешь проверить, написав простой пример:
(пересоздание нити на каждый запрос и обращение к уже существующей ).
Результат тебя впечатлит :)


 
Медвежонок Пятачок ©   (2009-02-21 21:54) [14]

сомневаюсь что меня это впечатлит.
я в основном занимаюсь проектированием систем 24х7.
пришел клиент - создается нить.
новая.
и никто еще пока не жаловался, что медленно обслуживается именно из за того, что нити пересоздаются.


 
Riply ©   (2009-02-21 22:03) [15]

> [14] Медвежонок Пятачок ©   (21.02.09 21:54)

Очень сильно зависит от интенсивности создания.
Предполагаю, что при "наплыве" клиентов - это может стать заметным.
P.S.
Ну и не зря же ThreadPool придумали :)


 
Медвежонок Пятачок ©   (2009-02-21 22:06) [16]

да. сред пул это как раз то что требуется кобальту.
или мы сейчас  решаем что требуется мне?


 
Riply ©   (2009-02-21 22:09) [17]

>  [16] Медвежонок Пятачок ©   (21.02.09 22:06)

Ты чего это такой агрессивный ? :)
Мы просто мирно обсуждали "тяжесть" создания нити,
а отнюдь не качество твоего кода :)


 
Медвежонок Пятачок ©   (2009-02-21 22:12) [18]

да я вообще пушистый.


 
Riply ©   (2009-02-21 22:15) [19]

> [18] Медвежонок Пятачок ©   (21.02.09 22:12)
> да я вообще пушистый.

Если еще и белый, то тогда ладно :)


 
Тын-Дын ©   (2009-02-21 22:53) [20]


> Медвежонок Пятачок ©   (21.02.09 21:10) [10]
>За какой надобностью здесь потребовалось
> использовать евенты?


Тебе интересно, или тебе подумать лень?

Конечно же, проще переться от собственной крутости, бросаясть фразами навроде [7].

Подумаешь - ответишь для себя.
Думать не хочешь - твоё дело.


 
Тын-Дын ©   (2009-02-21 22:54) [21]


> Медвежонок Пятачок ©   (21.02.09 21:05) [9]
> в чем-то ты прав. я не пытался ответить на них (вопросы)
> потому что таких вопросов у меня не возникало никогда


Ну не пытался, тогда стоит ли начинать пытаться? Тем более без практической и теоретической подготовки?


 
Cobalt ©   (2009-02-22 00:16) [22]

Мой вопрос был большей частью по эстетической линии:
Нет у потока свойства, которое бы показывало, работает он или нет (даже если Suspended)

Суть вопроса:
Есть несколько задач по обходу каталогов.
Сначала я сделал их в основном потоке, выводя в мемо результат обхода (с ProcessMessages для отображения пользователю).
Но при этом нажать на кнопку "Остановить процесс" затруднительно.
Вынес работу в отдельный поток, чтобы кнопки были доступны пользователю.

При этом надо обновлять состояние прочих кнопок в соответствии с состоянием работы.
Проще всего - по свойству потока - работает он или уже/еще нет.
К примеру, в Action.OnExecute дернул FThread.Start, а на Action.OnUpdate
actStop.Enabled:=FThread.Running;

а вместо этого приходится делать дополнительные свойства, вручную взводить в Thread.Execute и сбрасывать после:

actStop.Enabled:=(FThread<>nil)and(FThread.InProgress);


 
Медвежонок Пятачок ©   (2009-02-22 00:30) [23]

Тем более без практической и теоретической подготовки?

ты у меня экзамены что ли принимал?


 
Медвежонок Пятачок ©   (2009-02-22 00:33) [24]

Нет у потока свойства, которое бы показывало, работает он или нет (даже если Suspended)

и в чем проблема?
создать свойство с полем и менять его в execute?
не проблема.
только зачем?
для того что бы запустив поток тупо крутить цикл и проверять не приняло ли свойство нужное значнение?
дурь это.


 
Тын-Дын ©   (2009-02-22 00:33) [25]


> Нет у потока свойства, которое бы показывало, работает он
> или нет (даже если Suspended)


А что в твоём понимании "работает"?

Поток может находиться только в двух состояниях - спит и не спит.

Поточная функция может ожидать неких событий. В этом случае поток работает или нет?


 
Тын-Дын ©   (2009-02-22 00:35) [26]


> Медвежонок Пятачок ©   (22.02.09 00:30) [23]
> Тем более без практической и теоретической подготовки?ты
> у меня экзамены что ли принимал?


По твоему высказыванию видно -

> За какой надобностью здесь потребовалось использовать евенты?


Особенно вот это показывает полное непонимание предметной области-


> этот пример лучше никому не показывать, а самому втихаря
> переться от своей крутости.


 
Тын-Дын ©   (2009-02-22 00:36) [27]


> Медвежонок Пятачок ©


Если интересно понять, почему именно так, а не по другому - задай конкретные вопросы - по каждой строке кода отвечу.


 
Медвежонок Пятачок ©   (2009-02-22 00:36) [28]

евенты здесь нафик не нужны.

они могут понадобиться только от полного непонимания элементарный вещей.


 
Тын-Дын ©   (2009-02-22 00:40) [29]


> они могут понадобиться только от полного непонимания элементарный
> вещей.


Давай конкретнее? Не будем просто так языком чесать?


 
Германн ©   (2009-02-22 00:45) [30]


> Тын-Дын ©   (22.02.09 00:36) [27]


> Медвежонок Пятачок ©   (22.02.09 00:36) [28]

Классный спор!
Один доказывает, что Фома прав, поскольку он не забыл надеть шляпу, а другой доказывает, что Фома не прав, поскольку в отличие от Ерёмы у Фомы ноги кривые. :)
И ни один, ни другой не приводят в доказательство никаких фактов.
Хотя чету тут удивляться? Достаточно взглянуть на ники! :)

P.S. "Про ники" надеюсь без обид?
Попробуйте сами взглянуть на это со стороны.


 
Медвежонок Пятачок ©   (2009-02-22 00:51) [31]

Давай конкретнее? Не будем просто так языком чесать?

Давай.
Уточним, в чем суть спора.
создать один экземпляр нитки и иметь возможность запустить ее много раз повторно без пересоздания, но только тогда, кода она закончила всю прикладную работу с предыдущего вызова?

Верно? Я ничего не упустил?


 
Тын-Дын ©   (2009-02-22 00:57) [32]


> Медвежонок Пятачок ©   (22.02.09 00:51) [31]
> Давай конкретнее? Не будем просто так языком чесать?Давай.
> Уточним, в чем суть спора.создать один экземпляр нитки и
> иметь возможность запустить ее много раз повторно без пересоздания,
>  но только тогда, кода она закончила всю прикладную работу
> с предыдущего вызова?Верно? Я ничего не упустил?


Верно.


 
Медвежонок Пятачок ©   (2009-02-22 01:02) [33]

На.

Вот нитка

constructor TBearPigletThread.CreateIt(AHandle: THandle);
begin
inherited Create(True);
fHandle := AHandle;
FreeOnTerminate := False;
Resume;
end;

procedure TBearPigletThread.Execute;
var i : integer;
begin
for i := 1 to 10 do
 begin
  PostMessage(fHandle,WM_TEST,0,i);
  Sleep(500);
 end;
PostMessage(fHandle,WM_TEST,1,0);
end;

А вот вызывающий модуль

procedure TForm1.OnMsg(var AMsg: TMessage);
begin
case AMsg.WParam of
 0: ListBox1.Items.Add(IntToStr(AMsg.LParam));
 1: Button1.Enabled := True;
end;
end;

var t : TThread = nil;

procedure TForm1.Button1Click(Sender: TObject);
begin
if t = nil then TBearPigletThread.CreateIt(Handle) else t.Resume;
Button1.Enabled := False;
end;


 
Тын-Дын ©   (2009-02-22 01:07) [34]

Хм.
И где здесь повторная используемость?


 
Тын-Дын ©   (2009-02-22 01:08) [35]

Метод Execute заканчивает работу после одного прохода. ПТоток/нить на этому завершает своё существование.


 
Медвежонок Пятачок ©   (2009-02-22 01:09) [36]

Где повторная?
Под баттоном номер один.


 
Медвежонок Пятачок ©   (2009-02-22 01:10) [37]

ПТоток/нить на этому завершает своё существование.

А ты случаем не преподаватель информатики?
Что-то вдруг подумалось.


 
Тын-Дын ©   (2009-02-22 01:14) [38]


> if t = nil then TBearPigletThread.CreateIt(Handle) else
> t.Resume;


Можно пояснить, что здесь происходит?

Переменная t вроде бы не была кроме как nil проинициализирована?


 
Медвежонок Пятачок ©   (2009-02-22 01:19) [39]

какая разница?
зациклить execute и будет тоже самое.
никаких евентов здесь не надо.
переход в начало цикла или брейк - по результату SendMessage


 
Тын-Дын ©   (2009-02-22 01:26) [40]


> какая разница?
>зациклить execute и будет тоже самое.


Что значит - какая разница?
Покажи, как зациклишь.

Этот код в принципе не рабочий.

Ты рабочий код приведи.


 
Тын-Дын ©   (2009-02-22 01:27) [41]


> никаких евентов здесь не надо.


Не надо  так не надо.
Без эвентов покажи.


 
Медвежонок Пятачок ©   (2009-02-22 01:39) [42]

procedure TBearPigletThread.Execute;
var i : integer; NeedRun : boolean;
begin
while not Terminated do
 begin
  if fNeedRun then
   for i := 1 to 10 do
    begin
     PostMessage(fHandle,WM_TEST,0,i);
     Sleep(300);
    end;
  else
   Sleep(300);
  i := SendMessage(fHandle,WM_TEST,1,0);
  if i := 0 then Break else fNeedRun := i = 1;
 end;
end;


 
Тын-Дын ©   (2009-02-22 01:45) [43]


> Медвежонок Пятачок ©   (22.02.09 01:39) [42]


В твоём коде единственное, что делаеся - выполняется всё время один и тот же цикл. Причём непрерывно.

Если ты смотрел код в [4], то мог заметить, что в нём:

1. Поток после выполнения задания останавливается и ждёт появления новой задачи.
2. Для выполнения можно передавать разные функции - без пересоздания потока.


 
Тын-Дын ©   (2009-02-22 01:46) [44]

+ обрати внимание на задачу из топика.


 
Медвежонок Пятачок ©   (2009-02-22 01:47) [45]

и чего?
предлагаешь экономить на Create в то время как считаешь crc у дюжины файлов фик знает какого размера  и надеешься дофига выиграть?


 
Тын-Дын ©   (2009-02-22 01:48) [46]

+вопрос
А почему ты думаешь, что обмен может быть только с потоками, в которых окна есть?


 
Тын-Дын ©   (2009-02-22 01:51) [47]


> Медвежонок Пятачок ©   (22.02.09 01:47) [45]
> и чего?предлагаешь экономить на Create в то время как считаешь
> crc у дюжины файлов фик знает какого размера  и надеешься
> дофига выиграть?


Это типичная задача для пула потоков.
1. Если считать CRC у пары миллионов мелких файлов на диске, тем более, если это сетевой диск, выигрыш в скорости будет в десятки раз.
2. Про дюжину файлов можно говорить, если они находятся на дискете, что несколько неудобно.


 
Тын-Дын ©   (2009-02-22 01:52) [48]


> предлагаешь экономить на Create


Экономия не на Create, а на CreateThread.


 
Медвежонок Пятачок ©   (2009-02-22 01:56) [49]

А почему ты думаешь, что обмен может быть только с потоками, в которых окна есть?

если это консоль, то мне вообще странно применение нитки

отработала обработка и readln
Да/Нет/Не знаю


 
Тын-Дын ©   (2009-02-22 02:03) [50]


> если это консоль, то мне вообще странно применение нитки


А что тут странного?
Потоки работают в любом прложении.


> отработала обработка и readlnДа/Нет/Не знаю


Непонятно, однако.

Всё-таки хотелось бы видеть код, который реализует эти простейшие функции - выполнение процедуры в отдельном потоке, ожидание, передача новой процедуры для выполнения, корректное завершение.


 
Медвежонок Пятачок ©   (2009-02-22 02:05) [51]

я же показал уже


 
Медвежонок Пятачок ©   (2009-02-22 02:09) [52]

в обработчике формы либо выводим мессадждиалог и по нему присваиваем Msg.Result, либо по флагу, который взводится кнопкой.

и все крутится вертится.
но это для извращенцев. как и вариант с ожиданием евента.
когда считаешь црц файлов, на нитке не наэкономишь все равно.


 
Тын-Дын ©   (2009-02-22 02:09) [53]


> Медвежонок Пятачок ©   (22.02.09 02:05) [51]
> я же показал уже


Ты показал только стандартный цикл в методе Execute и обмен с оконной процедурой. Не более того.


 
Медвежонок Пятачок ©   (2009-02-22 02:10) [54]

Ты показал только стандартный цикл в методе Execute и обмен с оконной процедурой. Не более того.

С ожиданием евента цикл будет нестандартный а волшебный?


 
Тын-Дын ©   (2009-02-22 02:17) [55]


> Медвежонок Пятачок ©   (22.02.09 02:10) [54]
> Ты показал только стандартный цикл в методе Execute и обмен
> с оконной процедурой. Не более того.С ожиданием евента цикл
> будет нестандартный а волшебный?


Код в [4] выполняет задачу.
Твой - нет.

Вот потому тот код и волшебный.


 
Медвежонок Пятачок ©   (2009-02-22 02:26) [56]

не менее волшебный и без циклов и без евентов

procedure TBearPigletThread.Execute;
var i : integer;
begin
while not Terminated do
 begin
  for i := 1 to 10 do //Полезная работа
   begin
    PostMessage(fHandle,WM_TEST,0,i);
    Sleep(300);
   end;
  if SendMessage(fHandle,WM_TEST,1,0) = 0 then Suspend;
 end;
end;

procedure TForm1.OnMsg(var AMsg: TMessage);
begin
case AMsg.WParam of
 0 : ListBox1.Items.Add(IntToStr(AMsg.LParam));
 1 : begin
      Button1.Enabled := True;
      AMsg.Result := 0;
     end;
end;
end;

var t : TThread = nil;

procedure TForm1.Button1Click(Sender: TObject);
begin
if t = nil then t:= TBearPigletThread.CreateIt(Handle) else t.Resume;
Button1.Enabled := False;
end;


 
Тын-Дын ©   (2009-02-22 02:30) [57]

Сразу маленькая такая ошибка:


> procedure TForm1.Button1Click(Sender: TObject);begin if
> t = nil then t:= TBearPigletThread.CreateIt(Handle) else
> t.Resume; Button1.Enabled := False;end;


Здесь вот этот код - if t = nil then t:= TBearPigletThread.CreateIt(Handle) else t.Resume;, а именно  t.Resume сработает только в том случае, если поток уже "спит".
Это ведь неправильно?  Не так ли?


 
Тын-Дын ©   (2009-02-22 02:32) [58]

Кроме того, выполняется всё один и тот же цикл в поточной функции.
Это ведь тоже неправильно?


 
Медвежонок Пятачок ©   (2009-02-22 02:33) [59]

ну да. именно так и хотел автор
хотя можно сделать как хочется. и без всяких евентов.


 
Тын-Дын ©   (2009-02-22 02:34) [60]

При этом кто сказал, что поток сразу же должен выполнять некую полезную работу?
Он должен дождаться, когда ему передадут процедуру для выполнения и скомандуют об этом.


 
Медвежонок Пятачок ©   (2009-02-22 02:35) [61]

Кроме того, выполняется всё один и тот же цикл в поточной функции.

ну что за детсад? я могу запустить хоть тысячу разных алгоритмов с каждым новым нажатием кнопки. приведен просто пример нитки с подобием полезной работы


 
Тын-Дын ©   (2009-02-22 02:36) [62]


> Медвежонок Пятачок ©   (22.02.09 02:33) [59]
> ну да. именно так и хотел автор


Неправда.
Автор хотел нечто другое.

Дословно:
>  можно ли после окончания исполнения потока повторно использовать
> объект TThread ?


Повторное использование в данном случае - выполнение уже созданным потоком некоторой работы без создания нового потока.


 
Тын-Дын ©   (2009-02-22 02:37) [63]


> Медвежонок Пятачок ©   (22.02.09 02:35) [61]
> Кроме того, выполняется всё один и тот же цикл в поточной
> функции.ну что за детсад? я могу запустить хоть тысячу разных
> алгоритмов с каждым новым нажатием кнопки. приведен просто
> пример нитки с подобием полезной работы<


Вот не надо "некоего подобия".

Приведи рабочий, код, а не выжимки из него, который будет выполнять нужные задачи.


 
Медвежонок Пятачок ©   (2009-02-22 02:38) [64]

При этом кто сказал, что поток сразу же должен выполнять некую полезную работу?
Он должен дождаться, когда ему передадут процедуру для выполнения и скомандуют об этом.


ну передам я ему под кнопкой пойнтер с кучей полей в которых данные и указатели на мильон разных процедур и тыщщу колбаков и разбужу.

и все будет замечательно вертеться крутиться без евентов-моментов


 
Тын-Дын ©   (2009-02-22 02:39) [65]

Трындеть я тоже могу сколько угодно.
В коде в начале ветки не зря используются те же эвенты.
И приведён полный рабочий код.
И его немного.


 
Тын-Дын ©   (2009-02-22 02:40) [66]


> ну передам я ему под кнопкой пойнтер с кучей полей в которых
> данные и указатели на мильон разных процедур и тыщщу колбаков
> и разбужу.


Ну так передай. Покажи класс.


 
Медвежонок Пятачок ©   (2009-02-22 02:40) [67]

у меня преподавательский зуд много лет как прошел.


 
Медвежонок Пятачок ©   (2009-02-22 02:41) [68]

Трындеть я тоже могу сколько угодно.

продолжай трындеть.
а евенты здесь нахрен не нужны.

и я это показал.


 
Медвежонок Пятачок ©   (2009-02-22 02:44) [69]

Неправда.
Автор хотел нечто другое.

Дословно:
>  можно ли после окончания исполнения потока повторно использовать
> объект TThread ?

Повторное использование в данном случае - выполнение уже созданным потоком некоторой работы без создания нового потока.


у меня один поток в одном экземпляре после первого прогона повторно выполняет некторую работу по клику без создания нового потока.
и без дурацких евентов.


 
Медвежонок Пятачок ©   (2009-02-22 02:44) [70]

а еще и код в три раза компактнее дурацкого примера с евентами


 
Тын-Дын ©   (2009-02-22 02:45) [71]


> Медвежонок Пятачок ©   (22.02.09 02:41) [68]
> Трындеть я тоже могу сколько угодно.продолжай трындеть.а
> евенты здесь нахрен не нужны.и я это показал.


Нет, не показал. Только потрындел.

Код показан в [4].

Приведи класс полностью. Тогда можно будет говорить - показал или нет.

А сейчас - только разговор неконкретный.


 
Тын-Дын ©   (2009-02-22 02:46) [72]


> у меня один поток в одном экземпляре после первого прогона
> повторно выполняет некторую работу по клику без создания
> нового потока.


У тебя он выполняет не некую работу.
У тебя он выполняет всё тот же дурацкий цикл.


 
Медвежонок Пятачок ©   (2009-02-22 02:46) [73]

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


 
Тын-Дын ©   (2009-02-22 02:48) [74]


> Медвежонок Пятачок ©   (22.02.09 02:46) [73]
> ну что тебе показать?пиши. ради праздника покажу.


Я тебе уже написал.
Теперь дело за тобой - код в студию. Реализованный класс. Где так мало кода, где нет дурацких эвентов...


 
Тын-Дын ©   (2009-02-22 02:50) [75]

Кстати, и с эвентами, и без эвентов реализуется задача тривиально.
Но без эвентов мне твой код хочется увидеть, коль ты уж так здесь много понаписал против них.


 
Медвежонок Пятачок ©   (2009-02-22 03:31) [76]

Сначала нитка:

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 03:33) [77]

Теперь юзающий нитку модуль:

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;


 
Cobalt ©   (2009-02-22 03:46) [78]

Блин, я уже потерялся в ваших обсуждениях :)

Поясню, что же я хотел.
А хотел я собственно немногого - использовать именно класс 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:49) [79]

и что это меняет? в чем суть пробемы-то?


 
Тын-Дын ©   (2009-02-22 03:50) [80]

Ну вобщем-то всё нормально.
За исключением таких моментов:

1. Нет проверки на то, что поток занят выполнением. Отключение кнопок - это несерьёзно.
2. Код не защищён от одновременной попытки запуска нового задания.
Это приведёт к сложноуловимым ошибкам при выполнении в многопоточном приложении. Особенно на многопроцессорном компьютере.

Над этими проблемами ещё придётся поработать тому, кто возьмётся писать таким образом-)


 
Тын-Дын ©   (2009-02-22 03:52) [81]


> Cobalt ©   (22.02.09 03:46) [78]
>Т.е. дернул объект - тот запустил
> поток, обновил состояния, типа Terminated, Suspended и т.
> п.


И как часто у тебя такое происходит?
Может проще воспользоваться функцией QueueUserWorkItem?


 
Медвежонок Пятачок ©   (2009-02-22 03:54) [82]

твой класс- обертка над Thread - это у меня код TForm1

то есть все точно так же укладывается в эту модель.


 
жж   (2009-02-22 10:36) [83]

В данном случае никакая нить вообще не нужна.
ради доступности кнопки "отмена" городить весь огород - это лишнее.
Если бы задачка была фоновая сама по себе, а пользователь тем временем занимался бы в твоей программе чем то другим - то да, потоки, и все дела
а если он все равно будет сидеть ждать результатов, и максимум что может - отменить процесс, то задача решается вставкой обработок цикла сообщений приложением, и все.


 
Leonid Troyanovsky ©   (2009-02-22 10:43) [84]


> Cobalt ©   (21.02.09 15:14)  

> Например, запустив его метод Create - будет ли создан новый
> объект TThread, который повиснет в памяти, или он только
> отработает свой код, заново запустив WinAPI-ый поток исполняться?

Вызов как метода, т.е. T.Create(..), выполнит повторную инициализацию
объекта и запуск потока.

Раньше, в D3 еще, IMHO, у борландов в конструкторе был пропущен
inherited Create и фокус не проходил потому, что не обнулялись поля,
тот же самый FTerminated.

--
Regards, LVT.


 
Cobalt ©   (2009-02-22 11:31) [85]

2 Leonid Troyanovsky ©   (22.02.09 10:43) [84]

Спасибо, не был знаком с особенностями вызова конструктора у уже созданного объекта., спасибо :)


 
Тын-Дын ©   (2009-02-22 14:07) [86]


> Leonid Troyanovsky ©   (22.02.09 10:43) [84]
>Вызов как метода,
>  т.е. T.Create(..), выполнит повторную инициализациюобъекта
> и запуск потока.


При этом
1. будет потерян дескриптор нити (не освобождён) и все выделенные ресурсы, так как деструктор не отработает.
2. будет создана новая нить (а не повторно использоваться существующая).

Хотя автора это вполне может устраивать.


 
тимохов   (2009-02-22 18:23) [87]


> Leonid Troyanovsky ©   (22.02.09 10:43) [84]
>
> Раньше, в D3 еще, IMHO, у борландов в конструкторе был пропущен
>
> inherited Create и фокус не проходил потому, что не обнулялись
> поля,
> тот же самый FTerminated.

да вроде не в констукторе поля то обнуляются, а в прологе конструктора, типа NewInstance и InitInstance.


 
Leonid Troyanovsky ©   (2009-02-23 08:59) [88]


> тимохов   (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.


 
DVM ©   (2009-02-23 12:11) [89]


> Вызов как метода, т.е. T.Create(..), выполнит повторную
> инициализацию
> объекта и запуск потока.

Не надо так делать, несмотря на то, что возможно, будут утечки ресурсов, закончится все плохо. Тем более в данной конкретной задаче.


> Cobalt ©   (21.02.09 18:18) [6]
>
> > DVM ©   (21.02.09 17:28) [5]
> Так еще ж нужно знать, что он обошел всё, и всё подсчитал.
>

Ну и как это связано? Посчитал - уведомил кого надо, например главный поток, например сообщением и пошел себе считать дальше, или не пошел, а заснул до уведомления.


 
Игорь Шевченко ©   (2009-02-23 14:41) [90]

"Вот из-за этого у нас в стране и бардак, что всякие вроде вас создают индексы по пяти полям" (с) sql.ru


 
Leonid Troyanovsky ©   (2009-02-23 17:01) [91]


> Игорь Шевченко ©   (23.02.09 14:41) [90]

> "Вот из-за этого у нас в стране и бардак

Суров, брат :)

--
Regards, LVT.



Страницы: 1 2 3 вся ветка

Текущий архив: 2009.04.12;
Скачать: CL | DM;

Наверх




Память: 0.74 MB
Время: 0.015 c
15-1234438591
Урсулапов_
2009-02-12 14:36
2009.04.12
Как узнать описание имени компьютера в сети?


2-1235026821
CodeMaster
2009-02-19 10:00
2009.04.12
C++ to Delphi


15-1234352958
Правильный$Вася
2009-02-11 14:49
2009.04.12
как перенастроить APPDATA на другой диск?


2-1235218488
Cobalt
2009-02-21 15:14
2009.04.12
Запустить TThread повторно?


15-1234287680
Маэстро
2009-02-10 20:41
2009.04.12
Сколько это будет стоить?