Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.01.29;
Скачать: [xml.tar.bz2];

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.55 MB
Время: 0.009 c
6-93595
sr
2003-11-25 14:55
2004.01.29
Терминал


7-93727
Sam Stone
2003-11-12 19:36
2004.01.29
Файлы из кеша IE


3-93391
Andriy Tysh
2003-12-30 11:16
2004.01.29
DBGridEh.SumList


11-93410
mdw
2003-05-12 11:55
2004.01.29
destructor Destroy; (освобождение ресурсов)


1-93546
Сережа
2004-01-17 23:31
2004.01.29
Таймер





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский