Текущий архив: 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.OnUpdateactStop.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