Текущий архив: 2003.12.12;
Скачать: CL | DM;
Вниз
TThread Найти похожие ветки
← →
Alibaba © (2003-08-20 18:39) [0]Народ, помогите, не могу перезапустить поток.
1 Шаг.
constructor TM1Depend.Create;
begin
...
FreeOnTerminate:=False; //По окончанию не разрушается
inherited Create(True); //Создаем поток c ожиданием. Запуск: Resume
end;
2. Шаг
M1Depend.Resume;
3. Шаг
Обрабатываю результат
4. Шаг
M1Depend.Resume; НЕ РАБОТАЕТ!!!
← →
jack128 © (2003-08-20 21:19) [1]
> 3. Шаг
> Обрабатываю результат
Раз обрабатываешь результат, то поток уже отработал...
> 4. Шаг
> M1Depend.Resume; НЕ РАБОТАЕТ!!!
Естественно, поток то уже завершился...
FreeOnTerminate:=False; говорит о том, что объект Дельфей Tthread не будет разрушен, а вот объект Windows - thread уничтожается, как только он(поток) отработает...
← →
Alibaba © (2003-08-21 10:21) [2]Похоже, придется каждый раз создавать/удалять поток.
← →
panov © (2003-08-21 10:36) [3]Ты ведь не описал свою задачу.
Поэтому других решений никто пока предложить не может.
← →
Digitman © (2003-08-21 10:40) [4]
> Похоже, придется каждый раз создавать/удалять поток.
совершенно необязательно
возможный вариант :
procedure TM1Depend.Execute;
begin
while not Terminated do
begin
// здесь - вычисления и формирование результата
Suspend; // очередное дело сделано - можно чуток поспать, пока не разбудят извне
end;
end;
1 Шаг.
constructor TM1Depend.Create;
begin
...
// FreeOnTerminate:=False; //это св-во = False по умолчанию
inherited Create(True); //Создаем поток c ожиданием. Запуск: Resume
end;
2. Шаг
// передаем параметры для очередных вычислений в объект-поток
M1Depend.Resume; // разбудим поток - нехай считает
3. Шаг
// ждем результата , факт их наличия - Suspended = True
Обрабатываю результат
4. Шаг
// передаем другие параметры для очередных вычислений в объект-поток
M1Depend.Resume; // разбудим поток - нехай считает снова
5. Шаг
// ждем очер.результата , факт их наличия - опять же Suspended = True
Обрабатываю результат
6. Шаг
// командуем потоку - все, хватит, закругляйся !
M1Depend.Terminate; // собственно - команда
M1Depend.Reasume; // разбудим поток, первое что он сделает - проверит, не скомандовали ли ему флагом Terminated закруглиться
M1Depend.WaitFor; // ждем, пока поточная ф-ция завершится
M1Depend.Free; // собственно разрушаем отработавший объект M1Depend, управлявший поточной ф-цией
← →
Alibaba © (2003-08-22 12:07) [5]>Digitman © (21.08.03 10:40) [4]
Счас попробую....
← →
Alibaba © (2003-09-01 12:14) [6]>Digitman © (21.08.03 10:40) [4]
Спасибо. Все работает супер.
И каждый раз создавать поток ненадо!
← →
Digitman © (2003-09-01 15:45) [7]
> Alibaba
только подход такой (с Suspend и Resume) все равно есть и остается проктологическим)
← →
Polevi © (2003-09-01 15:58) [8]это не важно, главное что супер :)
← →
Alibaba © (2003-09-02 17:45) [9]>Digitman © (01.09.03 15:45) [7]
???
А какой же правильный????
← →
Polevi © (2003-09-02 18:04) [10]>Alibaba © (02.09.03 17:45) [9]
усыплять поток надо не Suspend"ом а с помощью Synchronization Functions - WaitForSingleObject к примеру
procedure TM1Depend.Execute;
begin
while not Terminated do
begin
WaitForSingleObject(SomeEvent,INFINTE);
end;
end;
4. Шаг
// передаем другие параметры для очередных вычислений в объект-поток
SetEvent(SomeEvent); // разбудим поток - нехай считает снова
← →
Polevi © (2003-09-02 18:06) [11]PS
ивент с автосбросом в данном примере
SomeEvent:=CreateEvent(nil,false,false,nil)
← →
Alibaba © (2003-09-02 18:49) [12]>Polevi © (02.09.03 18:04) [10]
Интерестный вариант.
Надо попробовать.
← →
Digitman © (2003-09-03 08:18) [13]
> Alibaba
или послпть потоку сообщение с пом. PostThreadMessage()
procedure TM1Depend.Execute;
begin
while not Terminated and GetMessage(...) do
begin
...
end;
end;
← →
AndreyAs (2003-09-03 10:26) [14]> Digitman ©
так в последнем примере поток, обработав сообщение, просто завершится, а не остановится?
← →
jack128 © (2003-09-03 13:01) [15]
> AndreyAs (03.09.03 10:26) [14]
GetMessage - ждет пока не придет сообщение и вернет false только когда в очереди wm_quit. Так что поток завершится либо по Terminate, либо если послать wm_quit.
А вообще прикольное ришение, мне очень понравилось...
← →
Digitman © (2003-09-03 13:13) [16]
> AndreyAs
условие завершения цикла наступит, когда поток примет сообщение WM_QUIT (GetMessage вернет False, во всех прочих случаях вернет True)
> jack128
> прикольное ришение
еще "прикольнее" решение с циклическим вызовом MsgWaitForMultipleObjects() .. в этом случае поток способен ждать и реагировать как на сообщения, ему (и его окнам) адресованные, так и на сигналы самых разнообразных штатных ОС-объектов синхронизации - мьютексы, семафоры, ивенты, процессы и т.д. и т.п.
← →
AndreyAs (2003-09-03 13:36) [17]> jack128 ©
> Digitman ©
Понял, сорри...
А не подскажете ли, как лучше поступить в моей задаче?
А именно:
Есть n потоков. Каждый из них выпоняет свою задачу, которую заканчивает с окончанием работы всего приложения.
Но в определенной точке работы какой-либо из потоков может создать ситуацию тиипа GlobalStop, то есть - у него сработало некоторое условие, в результае чего он должен сообщить всем остальным потокам "остановить работу и начать сначала".
Причем остановить ее надо мгновенно, не дорабатывая текущую итерацию до конца.
Сейчас я просто прибиваю все потоки и создаю их заново.
Но такой подход не устраивает. Как лучше поступить?
← →
Digitman © (2003-09-03 16:37) [18]
> AndreyAs
> Причем остановить ее надо мгновенно, не дорабатывая текущую
> итерацию до конца.
так в любом случае не получится.
даже если ты экстренно (принудительно) терминитуешь целевой тред вызовом TerminateThread() из другого треда, системе понадобится какое-то (пусть даже незначительное в рамках тек.процесса) время для снятия целевого треда с исполнения и освобождения конторолируемых системой ресурсов, ассоциированных с тредом ходе его создания и старта.
Я думаю, что нет ничего страшного собственно в выполнении какой-то части тек.итерации (в момент поступления сигнала на завершение). Другой вопрос, что в ходе этой итерации могут быть обращения к какому-то ресурсу, совместно используемому несколькими тредами, который в этот момент уже становится недоступным из-за принятия такого решения одним из тредов (подающим сигнал другим тредам). Необходимо предусмотреть какой-то общий для всех тредов объект синхронизации доступа к ресурсу, например, event. Основной тред создает его, дополнительные треды имеют право устанавливать его в сигн.состояние (если какой-то из них командует тем самым другим тредам на "закругление"). Перед тем как выполнить любой из крит.участков итерации, тред, заинтересованный в получении от других тредов такой команды на "закругление" вызывает WaitForSingleObject() с каким-то определенным параметром таймаута ожидания. Если в период этого таймаута event не просигналил (будучи установленный неким тредом в сигн.состояние), можно продолжать выполнение итерации, иначе - идти по и ной (предусмотренной тобой) ветке алгоритма
← →
AndreyAs (2003-09-04 18:28) [19]> Digitman ©
спасибо за ответ
а все-таки, если вернуться сюда:
while not Terminated and GetMessage(...) do
зачем посылать потоку сообщение? Могу я просто установить глобальную переменную, которую читает данный поток?
while not Terminated and FActive do
вроде работает
← →
Polevi © (2003-09-04 18:50) [20]>AndreyAs (04.09.03 18:28) [19]
не работает а жрет ресурсы, ибо GetMessage "усыпляет" поток
← →
Digitman © (2003-09-05 17:29) [21]
> AndreyAs
см. Polevi © (04.09.03 18:50) [20]
+ пока поток "спит" и не требует квантов проц.времени, он тем не менее будет "разбужен" системой в любой момент времени, при том не без явной пользы : ты посылаешь потоку (или одному из окон, возможно ранее потоком созданных) сообщение с какой-либо командой, и он тут же бросается ее выполнять
← →
Alibaba © (2003-10-03 17:31) [22]И так, чем отличаются два варианта запуска потоков:
Вариант №1 (Digitman © (21.08.03 10:40) [4])
procedure TM1Depend.Execute;
begin
while not Terminated do
begin
// здесь - вычисления и формирование результата
Suspend; // очередное дело сделано - можно чуток поспать, пока не разбудят извне
end;
end;
Вариант №2 (Digitman © (03.09.03 08:18) [13])
procedure TM1Depend.Execute;
begin
while not Terminated and GetMessage(...) do
begin
...
end;
end;
-Первый проще в реализации, но занимает ресурсы
-Второй сложнее, но во время ожидания не занимает ресурсы
Если так, то лучше, получается, второй?
← →
Verg © (2003-10-03 17:45) [23]
> Suspend; // очередное дело сделано - можно чуток поспать,
> пока не разбудят извне
А как упраляющий поток будет "ждать" suspended?
← →
Alibaba © (2003-10-03 17:58) [24]Не понятно откуда взялся термин упраляющий....
А M1Depend.Resume - делается из главной программы
← →
Verg © (2003-10-04 08:46) [25]
> 5. Шаг
> // ждем очер.результата , факт их наличия - опять же Suspended
> = True
> Обрабатываю результат
Так вот как же это "ждем"?
while not t.suspended do sleep(50); - так чтоль?
Или по таймеру проверять?
Я бы сделал так:
После завершения операции поток отправляет (postmessage) сообщение ГКП или его окну о завершении своей работы, и только после этого либо suspend, либо встает на ожидание сообщения типа "фас".
> А M1Depend.Resume - делается из главной программы
Не суть важно, главная или управляющая.
← →
Alibaba © (2003-10-04 13:56) [26]>Verg © (04.10.03 08:46) [25]
Все именно так и делается. :)
procedure TDepMain.Execute;
begin
while not Terminated do
begin
.............................
Чего-то делаем
.............................
PostMessage(frmMain.Handle,WM_DepMainMes,0,0);
Suspend;
end;
end;
← →
Verg © (2003-10-04 14:05) [27]Ну и славненько...
← →
Alibaba © (2003-10-05 00:30) [28]>Verg © (04.10.03 14:05) [27]
Тоесть, вы считаете, что это правильно?
Страницы: 1 вся ветка
Текущий архив: 2003.12.12;
Скачать: CL | DM;
Память: 0.55 MB
Время: 0.026 c