|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
Поток + Set|KillTimmer
Подскажите в чем может быть проблема.
Обработчик таймера Код:
procedure TЬForm.WMTimer(var Msg: TWMTimer); begin try try Thr.initWork(Msg.TimerID); // ShowMessage(BoolToStr(KillTimer(Self.Handle, msg.TimerID), True)); Msg.Result := 0; except end; finally KillTimer(Handle, Msg.TimerID); inherited; end; end; Код:
begin FLock.Enter; try if not FOnTime then begin fOnTime:=True; .... fOnTime:=false; end; finally FLock.Leave end; end; Код:
[14:11:42:253] Add Worker: Id: 1, Time: 7000 [14:11:42:759] Add Worker: Id: 2, Time: 8500 [14:11:43:264] Add Worker: Id: 3, Time: 10500 Последний раз редактировалось nixon232, 14.04.2018 в 15:26. |
#2
|
||||
|
||||
По Вашему коду остается только догадываться, что Вы пытаетесь сделать.
Могу предположить, что используется один дополнительный поток Thr и для него инициализирована одна критическая секция FLock. Для чего Вам FOnTime, и FLock? Грамотно поставленный вопрос содержит не менее 50% ответа. Грамотно поставленная речь вызывает уважение, а у некоторых даже зависть. |
#3
|
|||
|
|||
Цитата:
Я уже и через Property пробовал и все равно при втором проходе возвращает True. Хотя, по логике, если там True, то я бы уперся в крит. секцию. Неужели нужно паузу ставить в момент смены флага? |
#4
|
||||
|
||||
Цитата:
Грамотно поставленный вопрос содержит не менее 50% ответа. Грамотно поставленная речь вызывает уважение, а у некоторых даже зависть. Последний раз редактировалось dr. F.I.N., 15.04.2018 в 18:12. |
#5
|
|||
|
|||
Цитата:
Сам поток правда в цикле крутится с такой паузой в цикле Код:
... begin while not Terminated do begin case WaitForMultipleObjects(2, @FHandles[0], False, INFINITE) of WAIT_FAILED: RaiseLastOsError; WAIT_OBJECT_0: Terminate; WAIT_OBJECT_0 + 1: begin WaitMe(400); ... Код:
procedure WaitMe(msc: Cardinal); var Ret: Dword; WaitTime: TLargeInteger; Timer: THandle; begin // sleep without freezing Timer := CreateWaitableTimer(nil, True, nil); WaitTime := -msc * 10000; SetWaitableTimer(Timer, WaitTime, 0, nil, nil, false); repeat Ret := MsgWaitForMultipleObjects(1, Timer, false, INFINITE, QS_ALLINPUT); if Ret <> (WAIT_OBJECT_0 + 1) then Break; Application.ProcessMessages; until false; if Ret <> WAIT_OBJECT_0 then CancelWaitableTimer(Timer); CloseHandle(Timer); end; Код:
type TThr= class(TThread) private FHandles: array[0..1] of THandle; FLock: TCriticalSection; fOnTime: Boolean; ... procedure TThr.InitWork(id: Cardinal); begin FLock.Enter; try if not FOnTime then begin fOnTime:=True; .... fOnTime:=false; end; finally FLock.Leave end; end; Код:
Thr.initWork(1);/// fONTime =false, все ок, заходим, меняем флаг, работаем, меняем обратно Thr.initWork(2);/// fONTime =true Последний раз редактировалось nixon232, 15.04.2018 в 19:24. |
#6
|
||||
|
||||
Есть подозрение, что в основном потоке вы вызываете метод объекта Thr. InitWork где должен происходить? в основном или доп потоке?
Грамотно поставленный вопрос содержит не менее 50% ответа. Грамотно поставленная речь вызывает уважение, а у некоторых даже зависть. |
#7
|
|||
|
|||
Цитата:
Код:
procedure TMForm.WMTimer(var Msg: TWMTimer); begin **try ****try * ******Thr.initWork(Msg.TimerID); ... Последний раз редактировалось nixon232, 15.04.2018 в 19:57. |
#8
|
||||
|
||||
Ну, для передачи параметра в поток можно в доп-потоке сделать цикл сообщений и отправлять туда PostThreadMessage.
Еще раз повторюсь, я просто строю догадки о том, что Вы пытаетесь сделать. Есть вероятность, что я советую лишнее. Грамотно поставленный вопрос содержит не менее 50% ответа. Грамотно поставленная речь вызывает уважение, а у некоторых даже зависть. |
Этот пользователь сказал Спасибо dr. F.I.N. за это полезное сообщение: | ||
nixon232 (15.04.2018)
|
#9
|
|||
|
|||
Цитата:
Ну либо его стопать перед изменением? Ваша догадка про вызов из главного потока оказалось верной, если не вызывать явно InitWork, то флаг отрабатывает. Последний раз редактировалось nixon232, 15.04.2018 в 21:50. |
#10
|
||||
|
||||
Если хотите работать с объектом потока и менять его параметры или вызывать некую процедуру, можно либо создать в потоке очередь сообщений и из главного потока слать PostThreadMessage (как я уже писал), или сделать тоже самое на событиях.
Код:
type TThr = class (TThread) private FLock: TCriticalSection; FFiled: SomeType; FSetEvent: TEvent; function GetField: SomeType; procedure SetField(Value: SomeType); public property Field: SomeType read GetField write SetField; end; function GetField: SomeType; begin FLock.Enter; try Result := FField; finally FLock.Leave; end; end; procedure SetField(Value: SomeType); begin FLock.Enter; try FField := Value; finally FLock.Leave; end; FSetEvent.SetEvent; end; procedure Ececute(); begin Handles[N] := FSetEvent.Handle; case WaitForMultiplyObjects(...) of Wait_Object_0 + N: {сработало событие изменения поля}; end; end; Грамотно поставленный вопрос содержит не менее 50% ответа. Грамотно поставленная речь вызывает уважение, а у некоторых даже зависть. |
Этот пользователь сказал Спасибо dr. F.I.N. за это полезное сообщение: | ||
nixon232 (16.04.2018)
|
#11
|
|||
|
|||
Спасибо, более чем доходчивый пример.
|
#12
|
|||
|
|||
Попытался я реализовать вашу идею и что не получается. не подскажите в чем косяк?
Код:
while not Terminated do begin case WaitForMultipleObjects(3, @FHandles[0]{or @FHandles}, False , INFINITE) of WAIT_FAILED: RaiseLastOsError; WAIT_OBJECT_0: Terminate; WAIT_OBJECT_0 + 1: begin //some work end; WAIT_OBJECT_0 + 2: begin AddLogEvent;// сюда мы не попадаем. end; end; end; end; Код:
thr= class(TThread) private FHandles: array[0..2] of THandle; FLock: TCriticalSection; fLogEvent: string; ... function GetLogEvent: string; procedure SetLogEvent(const Value: string); ... protected ... procedure AddLogEvent; public ... published ... property LogEvent: string read GetLogEvent write SetLogEvent; ... end; Код:
procedure Thr.SetLogEvent(const Value: string); begin FLock.Enter; try if Value <> fLogEvent then begin fLogEvent := Value; SetEvent(FHandles[2]) end; finally Flock.leave; end; Код:
constructor Thr.Create(...); begin inherited Create(False); FHandles[0] := CreateEvent(nil, False, False, nil); // Управление завершением потока FHandles[1] := CreateEvent(nil, true, true, nil); // Управление паузой FHandles[2] := CreateEvent(nil, True, True, nil); // LogEvent .... SetEvent(FHandles[2]); //тестовый вызов, который не срабатывает end; Читал другие сайты, якобы нужно юзать WaitForSinglObject, но ведь WAIT_OBJECT_0 и WAIT_OBJECT_0+1 срабатывает? и не уверен, что передавать нужно @FHandles[0] или @FHandles? |
#13
|
||||
|
||||
Решил, что проще будет написать пример
И еще, WaitForSinglObject - используется для проверки единичного события, а WaitForMultipleObjects - для нескольких (третий параметр означает True - "ждать всех событий", False - "ждать любое событие из...") А что касается @FHandles[0] или @FHandles, то тут такая ситуация: Допустим у вас в массиве FHandles 5 хендлов событий и на текущей операции вы хотите отслеживать только с третьего, то передаете в качестве параметра ссылку на третий (не забудьте корректно указать количество отслеживаемых хендлов WaitForMultiplyObjects(3, @FHandles[2],...)). А если нужно отслеживать все, то указание @FHandles[0] или @FHandles равнозначно. Грамотно поставленный вопрос содержит не менее 50% ответа. Грамотно поставленная речь вызывает уважение, а у некоторых даже зависть. Последний раз редактировалось dr. F.I.N., 21.04.2018 в 14:20. |
Этот пользователь сказал Спасибо dr. F.I.N. за это полезное сообщение: | ||
nixon232 (21.04.2018)
|
#14
|
|||
|
|||
Цитата:
|