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

Вниз

Таймер не хочет работать...   Найти похожие ветки 

 
Chlavik ©   (2004-06-07 20:52) [0]

Вот код

procedure AddTimerUser;
begin
if not Assigned(GlobalTimerObj) then
 begin
  GlobalTimerObj:=TGlobalTimer.Create;
  GlobalTimerObj.Delay:=1000;
  GlobalTimerObj.Activate;
 end;
Inc(GlobalTimerUserCount);
end;

....

procedure TGlobalTimer.Activate;
begin
FID:=DefaultTimerID;
FID:=SetTimer(Handle,FID,FDelay,nil);
end;

...
TGlobalTimer=class(TMessageHandler)
TMessageHandler = обычный клас у которого есть WndProc и Handle

constructor TMessageHandler.Create;
begin
FHandle:=AllocateHWND(OnMessage);
inherited
end;


Так вот почемуто если первый раз вызвать  AddTimerUser с основного потока то всё пашет а вот если с другого то в wndproc не проходит wm_timer т.е. если создать экземпляр класса (GlobalTimerObj:=TGlobalTimer.Create) в другом потоке то не фига не работает, что делать ? Мне кажется что с процедурой AllocateHWND(OnMessage); что то не то творится если она не в основном потоке вызывается ... Помогите !


 
GuAV ©   (2004-06-07 21:12) [1]


>  если создать экземпляр класса (GlobalTimerObj:=TGlobalTimer.Create)
> в другом потоке

Код другого потока? может тупо Activate не вызывается?
и TGlobalTimer.Create на всяк случ


 
Chlavik ©   (2004-06-08 02:15) [2]

Дебаг показывает что всегда когда надо :)


 
Mim1 ©   (2004-06-08 02:42) [3]


> Мне кажется что с процедурой AllocateHWND(OnMessage); что
> то не то творится если она не в основном потоке вызывается
> ... Помогите !


А в  этом потоке есть цикл выборки вообщений?


 
Chlavik ©   (2004-06-08 02:49) [4]


procedure TMessageHandler.OnMessage(var Message: TMessage);
begin
Dispatch(Message);
end;

причём виртуальный
а у TGlobalTimer есть

procedure OnTimer(var Message:TWMTimer); message WM_TIMER;



 
Mim1 ©   (2004-06-08 03:15) [5]

Насколько велик код "неосновоного потока", может его сюда закинуть?


 
Digitman ©   (2004-06-08 09:17) [6]


> Chlavik ©   (08.06.04 02:49) [4]


и вот это ты называешь "циклом" ?


 
Chlavik ©   (2004-06-08 14:24) [7]

А за зачем мне цикл?????? С помощью AllocateHWND(OnMessage); я связываю процедуру обработки сообщений OnMessage с хэндлом ... всё должно работать без всяких циклов ... Может кто топредалгает сделать еще один цикл с GetMessage ? но это же помойму чють не то ..


 
Chlavik ©   (2004-06-08 14:29) [8]

Как же тогда создаются окна в других потоках?? цикл обработки сообщений у приложения вить то один!!??


 
Digitman ©   (2004-06-08 14:42) [9]


> Chlavik ©   (08.06.04 14:24) [7]



> А за зачем мне цикл??????


за надом !


> всё должно работать без всяких циклов


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


> Может кто топредалгает сделать еще один цикл с GetMessage


я предлагаю ...хоть с GetMessage, хоть с PeekMessage, но сообщения должны тем или иным образом выбираться из очереди и либо обрабатываться непосредственно либо диспетчеризоваться штатным для оконного механизма образом - по DispatchMessage()


> Как же тогда создаются окна в других потоках??


окна в любых потоках создаются одинаково - вызовом CreateWindow[Ex]


> цикл обработки сообщений у приложения вить то один!!??


по умолчанию - да, один ... его за тебя сделал и запустил Борланд в методе Application.Run .. и цикл там ответственен за ожидание/выборку/диспетчеризацию сообщений ОСНОВНОМУ потоку, который по умолчанию и безусловно создается при старте любого процесса

если же ты создал еще один или более доп.код.потоков, то ТЫ САМ (а не Борланд !) ответственен за создание очереди сообщений и за создание/работу цикла ожидания/выборки/обработки/диспетчеризации сообщений потоку и окнам, созданным в его контексте


 
Digitman ©   (2004-06-08 14:50) [10]


> Chlavik


осознай главное - поток А знать ничего не знает и не обязан знать ни о каких сообщениях какому-либо иному потоку В

каждый поток ответственен за самостоятельную организацию СОБСТВЕННОЙ очереди сообщений и алгоритма обработки этой очереди

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


 
Mim1 ©   (2004-06-08 15:47) [11]

Хочется добавить "Никакого VCL в неосновном потоке".
И еще, может в дополнительном потоке обойтись без таймера. Например sleep.


 
Digitman ©   (2004-06-08 15:58) [12]


> Mim1 ©   (08.06.04 15:47) [11]



> Никакого VCL в неосновном потоке


ты неправ

к примеру, никто и ничто не ограничивает тебя в создании невидимого по умолчанию объекта-наследника класса TForm и монопольного обращения к многим методам/св-вам этого VCL-объекта.. и никаких исключенийт при этом не получишь ... проблемы же начнутся как минимум с момента попытки выполнить метод Show[Modal]() этой формы


> может в дополнительном потоке обойтись без таймера


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


 
Chlavik ©   (2004-06-08 17:22) [13]

Просто таймер через PulseEvent сбрасиывет hEvent который юзают многие потоки вот в чём прикол ...


> Например sleep


Sleep а потом еще выполнение кода - вряме между итерациями цикла далеко будет не столько сколько надо ...


 
Chlavik ©   (2004-06-08 17:29) [14]


> если же ты создал еще один или более доп.код.потоков, то
> ТЫ САМ (а не Борланд !) ответственен за создание очереди
> сообщений и за создание/работу цикла ожидания/выборки/обработки/диспетчеризации
> сообщений потоку и окнам, созданным в его контексте


Thank"s ... не знал... Я думал что цикл один на весь процесс. Тогда всё понятно...


 
Digitman ©   (2004-06-08 17:31) [15]


> Просто таймер через PulseEvent сбрасиывет hEvent который
> юзают многие потоки вот в чём прикол ...


чавой-тооо ? это здесь при чем ? прежде чем что-то по какому-то поводу выполнило АПИ-вызов PulseEvent(), это "что-то" должно получить управление, будучи вызванным на исполнение тем или иным образом ... без цикла и без диспетчеризации никто и ничто не  передаст управление на фрагмент кода, выполняющий PulseEvent() !!


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


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


 
Chlavik ©   (2004-06-08 17:38) [16]

procedure TGlobalTimer.OnTimer(var Message: TWMTimer);
begin
PulseEvent(FhEvent);
end;

while not Terminated do
 begin
  WaitForMultipleObjects(Length(FWaitObjects),@FWaitObjects,false,INFINITE);
  Inc(FDelayCount);
  if FDelayCount>FTimeOut then Include(FStatus,tsTimeOut);
  if Assigned(FOnTimer) then DoOnTimer;
 end;
где FWaitObjects[0] это тот самы hEvent

Это заниматся дурью... ???


 
Digitman ©   (2004-06-08 17:44) [17]


> Chlavik ©   (08.06.04 17:38) [16]


> Это заниматся дурью... ???


а то нет !?

не дурь ли не анализировать в дан.случае рез-т выполнения WaitForMultipleObjects() !?

я ведь понятия не имею, какой трэд создает ивент-объект ... а ну как WaitForMultipleObjects() вернет WAIT_ABANDONED_+  ... ?!!


 
Chlavik ©   (2004-06-08 17:53) [18]

Не спеши тема другая была, дай код доописать ....


 
Chlavik ©   (2004-06-08 17:57) [19]

Ды и при чём тут WAIT_ABANDONED  к Event object ???? Это же не Mutex !!!


 
Mim1 ©   (2004-06-08 20:09) [20]


> > Например sleep


Я считаю что это наиболее красивое решение полскольку держать очередь сообщений только для поддержания таймена это нагрузка на вану программу и систему в целом. (однако есть некоторые неприятные нюансы которые я укажу в конце этого поста).

Если подход со слипом вас устраивает то


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


Вы же знаете сколько сколько надо? :)
тогда код с вот таким шаблоном вам поможет

// предположим что вам надо чтобы ваш код срабатывал каждую секунду
// тогда

procedure execute;
var dw:dword;
begin
 while true do
   begin
     if terminated then exit;  

     dw := gettickcount;
     // делаем некоторую задачу
     dw := 1000 - gettickcount - dw;

     if terminated then exit;  

     sleep(dw);
   end;
end;


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


 
Chlavik ©   (2004-06-09 01:27) [21]

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


 
Mim1 ©   (2004-06-09 03:56) [22]


> что со системой будет ... .

И что будет с системой? Зачем вам высокий приоритет? И каким боком вопрос о приоритетах относится к вопросу о таймерах?



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

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

Наверх




Память: 0.53 MB
Время: 0.025 c
14-1086258358
vecna
2004-06-03 14:25
2004.06.20
Ой... Каспера поймали =)


14-1086001753
Gero
2004-05-31 15:09
2004.06.20
MP3 музыка


6-1083243303
Koba
2004-04-29 16:55
2004.06.20
Содержимое каталога


3-1085648391
Marik
2004-05-27 12:59
2004.06.20
Снова про поиск


11-1075639173
Vladimir Kladov
2004-02-01 15:39
2004.06.20
замена sysdcu для D4 - by Thaddy de Koning