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

Вниз

TThread + TTimer   Найти похожие ветки 

 
snake1977   (2004-01-15 11:14) [0]

Здравствуйте! Такая вот задача: есть несколько модулей в каждом из которых, с определенным интервалом времени должны выполняться определенные процедуры. Для того чтобы выполнение этих ппроцедур не мешало выполнению других процессов, я решил использовать TThread в котором запускаю таймер. Честно, я первый райз использую TThread и взял примерчик с этогоже сайта из статьи, но так и не понял как же мне запускать таймер в организованном потоке%((. Подскажите примером, как организовать такую вот работу.

вот то что у меня написано:
type TMyThread = class(TThread)
protected
procedure DoWork;
procedure Execute; override;
end;
implementation

procedure TMyThread.Execute;
begin
while not Terminated do
Synchronize(DoWork);
end;

procedure TMyThread.DoWork;
begin
....
end;


 
Семен Сорокин ©   (2004-01-15 11:18) [1]

в Thread организовать таймер можно с помощью Sleep или GetTickCount внутри цикла.


 
Тимохов ©   (2004-01-15 11:19) [2]

procedure TMyThread.Execute;
begin
while not Terminated do
begin
Synchronize(DoWork);
sleep(10000)
end
end


 
Dred2k ©   (2004-01-15 11:24) [3]

Таймер в нитке??? Оригинально...
Просто засекай время по GetTickCount, отсчитывай и действуй в нужные моменты. А TTimer работает по событию, приходящему в форму (фактически - в рамках главной нити приложения). Кроме того, Synchronize сводит на нет весь эффект от использования отдельной нитки. Разделяй доступ к ресурсам через TCriticalSection или TEvent. Если нужно что-то "рисовать" (обращаться к VCL-объектам) - посылай сообщения через PostMessage, это надежно и довольно удобно.


 
snake1977   (2004-01-15 11:26) [4]

а в каком модуле описана процедура sleep ??
компилятор ругается что "неизвестный идентификатор sleep"


 
Digitman ©   (2004-01-15 11:28) [5]


> А TTimer работает по событию, приходящему в форму (фактически
> - в рамках главной нити приложения)


с какой это стати ?
тот код.поток, который создал экз-р TTimer, и будет извещаться о событиях созданного таймера... будет это осн.поток или доп.поток - значения не имеет


 
snake1977   (2004-01-15 11:29) [6]

>> Dred2k
>>Кроме того, Synchronize сводит на нет весь эффект от >>использования отдельной нитки

а по подробнее?? почему на нет сводит эффект?? и как тогда сделать чтобы каждая такая нить выполнялась паралельно?


 
Dred2k ©   (2004-01-15 11:29) [7]

Windows


 
Романов Р.В. ©   (2004-01-15 11:32) [8]

Запускай поток по таймеру расположенному на главной форме.
И зачем нужен поток когда все его операции выполяются в основном потоке
while not Terminated do
Synchronize(DoWork);
end;


 
snake1977   (2004-01-15 11:32) [9]

>>Digitman ©
так как засунуть то в поток таймер??
т.е. в процедуре execute фактически крутиться бесконечный цикл (ну до terminate есесно), а таймер срабатывает по событию.....
чего мне написатьто тогда в Execute??


 
Digitman ©   (2004-01-15 11:32) [10]


> snake1977


просто не используй Synchronize(), либо разберись в обоснованности использования этого метода в каждом конкретном случае


 
Dred2k ©   (2004-01-15 11:32) [11]

> Digitman © (15.01.04 11:28) [5]

Ага, WM_TIMER по потокам гулять будет...


 
Тимохов ©   (2004-01-15 11:35) [12]

Все таки не понял, чем sleep то не подходит? Или GetTickCount? Зачача то ведь решится.


 
snake1977   (2004-01-15 11:35) [13]

>>Романов Р.В. ©
>>Запускай поток по таймеру расположенному на главной форме.
должно крутиться несколько потоков одновременно.
>>
>>И зачем нужен поток когда все его операции выполяются в >>основном потоке
>>while not Terminated do
>> Synchronize(DoWork);
>>end;

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


 
snake1977   (2004-01-15 11:37) [14]

>>>Тимохов ©
Во время Sleep, что присходит с основным и другими потоками??
они продолжают свое выполнение или останавливаются?


 
Dred2k ©   (2004-01-15 11:38) [15]

> snake1977 (15.01.04 11:29) [6]

Synchronize(DoWork); выполнит DoWork в рамках основной нитки приложения. То есть все нитки, фактически, будут постоянно друг друга ждать. Сия вещь нужна для корректной отработки вызовов к визуальным компонентам VCL. А так - зачем оно тебе? Нить считает, да считает... Если есть общие области данных (переменные и т.п.) - разделяй через критические секции или евенты. Как я уже говорил, можно и отображать без ожидания - сделай в окне общий обработчик своего собятия и посылай последнее из ниток без ожидания, в событие впихивай указатели на данные для отображения, освобождай по факту отображения - схема нормальная... Почитай про нитки - иначе сложно все это на коленке объяснять.


 
Тимохов ©   (2004-01-15 11:38) [16]

snake1977 (15.01.04 11:37) [14]
Слип влияет на поток, в котором вызван.


 
Семен Сорокин ©   (2004-01-15 11:39) [17]

Во время Sleep, что присходит с основным и другими потоками??
конечно продолжают работать, засыпает только поток, в котором ты делаешь Sleep


 
Digitman ©   (2004-01-15 11:39) [18]


> Dred2k © (15.01.04 11:32) [11]

> Ага, WM_TIMER по потокам гулять будет...


что значит "гулять" ?
тот поток, который вызвал SetTimer(), и будет получть адресованные ему (или окнам им созданным) индивидуальные WM_TIMER


 
panov ©   (2004-01-15 11:42) [19]

>Dred2k © (15.01.04 11:32) [11]

Ага, WM_TIMER по потокам гулять будет..

С чего бы это?
В классе TTimer создается невидимое окно, которому и отсылается сообщение. И неважно, где создается таймер, в основном потоке, или в дополнительном.


 
Dred2k ©   (2004-01-15 11:45) [20]

> panov © (15.01.04 11:42) [19]

Я о том же и говорил.

> Digitman © (15.01.04 11:39) [18]

Поток ничего получать не будет.


 
Digitman ©   (2004-01-15 11:56) [21]


> Dred2k © (15.01.04 11:45) [20]


> Поток ничего получать не будет


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

об основном потоке приложения позаботился сам Борланд, написав для "батонокидателей" метод Application.Run и вызывая его при инициализации GUI-приложения

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


 
snake1977   (2004-01-15 11:58) [22]

>>>Digitman ©

>>.... в том или ином виде логику приема/диспетчеризации/обработки этих сообщений...

подскажи где мона почитать об этом??


 
Тимохов ©   (2004-01-15 12:01) [23]

Глянь как сделано в TApplication.Run.


 
YuRock ©   (2004-01-15 12:04) [24]

> Digitman © (15.01.04 11:56) [21]
> об основном потоке приложения позаботился сам Борланд
> об дополнительных же Борланд заботиться вовсе не обязан

Да... Спасибо, конечно, Борланду. Если бы он еще так "позаботился" о главном потоке, чтобы из других потоков можно было бы хотябы слать сообщения через SendMessage окнам, созданным в главном потоке...
А так (при возникновении необхоимости, например, прорефрешить окно из другого потока) приходится либо постить сообщение, либо вообще отказываться от Application.Run ...


 
Digitman ©   (2004-01-15 12:06) [25]


> snake1977 (15.01.04 11:58) [22]


для начала скажи, почему

"я решил использовать TThread в котором запускаю таймер"

а не

"я решил использовать таймер в котором запускаю TThread"

?

мне пока неясна твоя логика, а от этого и решение/рекомендация зависит


 
Dred2k ©   (2004-01-15 12:10) [26]

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


Это мудро. Оценил.

> организация подобной логики в доп.потоках

Сообщение получит окошко, и плевать на то, какой поток его создал - забота системы. Винды, понимаешь... Без окошек - никуда.


 
Verg ©   (2004-01-15 12:17) [27]


> Сообщение получит окошко, и плевать на то, какой поток его
> создал - забота системы. Винды, понимаешь... Без окошек
> - никуда.


Окошко-то получит, а кто его (сообщение) заберет(обработает), а? Какой поток?


 
Digitman ©   (2004-01-15 12:22) [28]


> Dred2k © (15.01.04 12:10) [26]


> Сообщение получит окошко, и плевать на то, какой поток его
> создал - забота системы. Винды, понимаешь... Без окошек
> - никуда.


это не верно.
не оценил.

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

и без окошек как раз "куда" ! ибо сообщение м.б. послано как окну, так и кодовому потоку... оба варианта вполне документированы и полностью работоспособны ... см. PostThreadMessage() - увидишь, что никакие окошки в параметрах этой ф-ции не фигурируют


 
AKul ©   (2004-01-15 12:23) [29]


> Dred2k © (15.01.04 11:24) [3]
> TTimer работает по событию, приходящему
> в форму (фактически - в рамках главной нити приложения).
>


Это Borland заставило его так работать (передавать событием).
Но Timer (Windows API) сам может вызывать процедуру, передаваемую ему при создании (используется callback).


 
Dred2k ©   (2004-01-15 12:23) [30]

> Окошко-то получит, а кто его (сообщение) заберет(обработает), а? Какой поток?

В контексте потока-создателя и обработается. Есть варианты, а?...


 
Digitman ©   (2004-01-15 12:25) [31]


> Dred2k


Win32 предусматривает отдельные очереди для сообщений, адресованных код.потокам и сообщений, адресованных окнам (неважно какими код.потоками созданным)


 
YuRock ©   (2004-01-15 12:28) [32]

> Verg © (15.01.04 12:17) [27]
> ошко-то получит, а кто его (сообщение) заберет(обработает), а? Какой поток?

Обработает его оконная процедура. В потоке, в котором создано окно.


 
Digitman ©   (2004-01-15 12:28) [33]


> Dred2k © (15.01.04 12:23) [30]
>
> В контексте потока-создателя и обработается. Есть варианты,
> а?...


есть.
см. AttachThreadInput(), позволяющая код.потоку 2 делать выборку из очереди сообщений потока 1


 
Dred2k ©   (2004-01-15 12:29) [34]

> Digitman © (15.01.04 12:22) [28]

> сообщение в любом случае получает не окошко, а кодовый поток

Не факт. Может и не получить.

The function fails if the specified thread does not have a message queue. The system creates a thread"s message queue when the thread makes its first call to one of the Win32 USER or GDI functions.


 
Digitman ©   (2004-01-15 12:30) [35]


> > Dred2k


"выборка сообщений" и "обработка сообщений" - две разные вещи, не путай


 
Nikolay M. ©   (2004-01-15 12:31) [36]


> чтобы выполнение этих ппроцедур не мешало выполнению других
> процессов, я решил использовать TThread в котором запускаю
> таймер

RX-овый RxTimer, что-ли, пишется? Дык он вроде уже написан...


 
AKul ©   (2004-01-15 12:32) [37]

Еще раз повторюсь:
Это Borland заставило его так работать (передавать событием).

Но можно использовать API-функцию SetTimer, которую настроить на вызов заданной процедуры (HWND=0).


 
Verg ©   (2004-01-15 12:34) [38]


> Но можно использовать API-функцию SetTimer, которую настроить
> на вызов заданной процедуры (HWND=0).


Из Help-а по SetTimer

When you specify a TimerProc callback function, the default window procedure calls the callback function when it processes WM_TIMER. Therefore, you need to dispatch messages in the calling thread, even when you use TimerProc instead of processing WM_TIMER.


 
Dred2k ©   (2004-01-15 12:38) [39]

> Digitman © (15.01.04 12:30) [35]

> "выборка сообщений" и "обработка сообщений" - две разные
> вещи, не путай


Ты насчет > Dred2k © (15.01.04 12:29) [34]
?

Обработка без выборки? Интересно...
Тем паче, что нет очереди - нет и содержимого. Тоже ведь вариант.


 
Digitman ©   (2004-01-15 12:40) [40]


> Dred2k © (15.01.04 12:29) [34]
> > Digitman © (15.01.04 12:22) [28]
>
> Не факт. Может и не получить.


"в любом случае" - здесь имелось ввиду не гарантия доставки сообщения, а то что именно кодовый поток ответственен за выборку сообщений изо всех его интересующих (и ассоциированных с ним и его окнами) очередей


> The function fails if the specified thread does not have
> a message queue. The system creates a thread"s message queue
> when the thread makes its first call to one of the Win32
> USER or GDI functions.


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

поэтому одним из грамотных подходов к реализации корректной логики является следующий :

поток-отправитель :
while not PostThreadMessage() do ..

поток-получатель же должен сразу после старта как можно быстрее вызвать любую из ф-ций, отвечающих за выборку сообщений из очереди (при первом же вызове очередь будет создана), например :

PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE)



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

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

Наверх




Память: 0.58 MB
Время: 0.029 c
3-93352
mail
2004-01-03 14:42
2004.01.29
Paradox - пробелы в названии полей


7-93717
Михаил
2003-11-10 16:42
2004.01.29
Кто-нибудь знает как в ХР можно нажимать программно кнопки?


1-93491
Shc
2004-01-12 18:47
2004.01.29
Поиск по XML схеме


7-93722
AXE_
2003-11-14 11:57
2004.01.29
обмен файлами через модем


1-93565
MakNik
2004-01-15 12:23
2004.01.29
TEdit