![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
|||
|
|||
|
Подскажите в чем может быть проблема.
Обработчик таймера Код:
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? |
|
#3
|
|||
|
|||
|
Цитата:
Я уже и через Property пробовал и все равно при втором проходе возвращает True. Хотя, по логике, если там True, то я бы уперся в крит. секцию. Неужели нужно паузу ставить в момент смены флага? |
|
#4
|
||||
|
||||
|
Цитата:
Последний раз редактировалось 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 где должен происходить? в основном или доп потоке?
|
|
#7
|
|||
|
|||
|
Цитата:
Код:
procedure TMForm.WMTimer(var Msg: TWMTimer); begin **try ****try * ******Thr.initWork(Msg.TimerID); ... Последний раз редактировалось nixon232, 15.04.2018 в 19:57. |
|
#8
|
||||
|
||||
|
Ну, для передачи параметра в поток можно в доп-потоке сделать цикл сообщений и отправлять туда PostThreadMessage.
Еще раз повторюсь, я просто строю догадки о том, что Вы пытаетесь сделать. Есть вероятность, что я советую лишнее. |
| Этот пользователь сказал Спасибо 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; |
| Этот пользователь сказал Спасибо 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 равнозначно. Последний раз редактировалось dr. F.I.N., 21.04.2018 в 14:20. |
| Этот пользователь сказал Спасибо dr. F.I.N. за это полезное сообщение: | ||
nixon232 (21.04.2018)
| ||
|
#14
|
|||
|
|||
|
Цитата:
|