Форум: "Основная";
Текущий архив: 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.01 c