![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Поток, организация проверки раз в секунду PostThreadMessage
AV © (2012-07-31 10:52:00)До этого не пользовался сообщениями, через проперти пинал потоки.
Правильно понимаю линию партии?
поток
procedure TMyTH.Execute;
var Msg: TMsg;
begin
repeat
if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
begin
DT := Msg.message;
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
Sleep(1000);
if DT = MyMessage then ; //Synchronize(Update);
DT := 0;
until Terminated;
end;
оповещение
T1 := TMyTH.Create(false);
PostThreadMessage(T1.ThreadID, WM_USER, 0, 0);
Dennis I. Komarov (2012-08-02 18:39:00) [1]
> Вот и думаю, где. Поток по идее не знает, кого ему ждать.
>
> а скормил что-то, первое попавшееся, пусть по таймату и
> отваливает. Но тогда и слип пойдет, в принципе..
>
А ждать он должен наступления события и не секунду, а пока не наступит (иу или...)
наступило - поехали, нет - сидит поток тихо и не вякает... и всем хорошо :)
AV (2012-08-02 11:20:00) [2]Вот и думаю, где. Поток по идее не знает, кого ему ждать.
а скормил что-то, первое попавшееся, пусть по таймату и отваливает. Но тогда и слип пойдет, в принципе..
> Leonid Troyanovsky © (01.08.12 16:31) [16]
гуглем находил :)
Непонятно уже самуму что хочу.
Надо задаяу поставить себе четче..
Тогда я пока почитать и сформулировать
Dennis I. Komarov (2012-08-01 19:45:00) [3]
> > WaitForSingleObject(hEvent
>
> да, так
> и он должен сигналить
А ты ему что скормил? Отваливает он по time-out и ничего более, так где смысла?
Leonid Troyanovsky (2012-08-01 16:31:00) [4]
> AV © (01.08.12 13:24) [15]
http://rsdn.ru/forum/delphi/883505.1.aspx
--
Regards, LVT.
AV (2012-08-01 13:24:00) [5]
> WaitForSingleObject(hEvent
да, так
и он должен сигналить
> кроме собственно синхронной обработки этих сообщений они
> больше ничем не занимаются.
сейчас так, они просто друг друга пинают :)
Я к чему подвожу все это безобразие..
потом потоки(, окна, етц. )
будут ждать только сообщение.
В W|L параметрах куда положить результат.
Посчитали, положили по адресу, ответили .
Один диспетчер, который принимает все сообщения от всех и раздает их всем остальным. Кому нужна реакция тот пусть реагирует.
т.е. кто-то захотел посчитать то, что умеет Т1. Он пуляет сообщение диспетчеру. Диспетчер всем раздает. Т1 узнает себя и начинает работать, остальные игнорируют, т.к. сообщение им не известно.
Некоторые заинтересовались, т.к. им известно что это такое.
Т1 посчитал, ответил диспетчеру. Диспетчер всем раздал.
Кто просил получил
И кто заинтересовался до этого, тоже получил.
Кто опять не понял - опять проигнорировал.
итого, все обязаны знать только диспетчера.
и логика работы у всех одинаковая
Dennis I. Komarov (2012-08-01 13:10:00) [6]
> это же только пример, реальность несколько другая :)
Опиши реальность, а то пока полная ерунда...
> тока не надо, и так достаточно.
> + я так лучше понимаю :)
Это тебя не оправдывает :)
Dennis I. Komarov (2012-08-01 12:20:00) [7]
> WaitForSingleObject(MainThreadID, 1); // или без разницы,
> просто ждать
WaitForSingleObject( hEvent, ...) is function
P.S. Могу наврать, Delphi нет под рукой...
Сергей М. (2012-08-01 11:49:00) [8]
> AV © (01.08.12 09:28) [11]
>
> А кого они должны ждать?
Ну в твоем случае никого/ничего кроме адресованных им сообщений они не ждут. И кроме собственно синхронной обработки этих сообщений они больше ничем не занимаются.
А раз так, то PeekMessage со слипом впридачу ничем, imho, не оправдан.
А раз не оправдан, то значит ждать и выбирать свои сообщения твоим потокам нужно переходя в kernel-time - GetMessage(или ее эквивалент WaitMessage+ PeekMessage)
AV (2012-08-01 09:28:00) [9]А кого они должны ждать?
ли без разницы, просто ждать, что бы быть готовым?
TMyTH = class(TThread)
private { Private declarations }
DT: Cardinal;
CNT: Integer;
protected
procedure Execute; override;
procedure Update;
public
FName: string;
FMSG: Cardinal;
T: TMyTH;
end;
procedure TMyTH.Execute;
var Msg: TMsg;
begin
while not Terminated do
begin
if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
begin
DT := Msg.message;
DispatchMessage(Msg);
end else
WaitForSingleObject(MainThreadID, 1); // или без разницы, просто ждать
if DT = FMSG then
begin
DT := 0;
CNT := CNT + 1;
if T <> nil then
PostThreadMessage(T.ThreadID, T.FMSG, 0, 0);
Update;
end;
end;
end;
procedure TMyTH.Update;
begin
try
EnterCriticalSection(Form1.CS);
form1.mmo1.Lines.Add( FName + ' ' + IntToStr(GetTickCount));
finally
LeaveCriticalSection(Form1.CS);
end;
end;
----
T1 := TMyTH.Create(true);
T1.FName := 'T1';
T1.FMSG := WM_USER + 1;
T2 := TMyTH.Create(true);
T2.FName := 'T2';
T2.FMSG := WM_USER + 2;
T1.T := T2;
T2.T := T1;
InitializeCriticalSection(CS);
T1.Resume;
T2.Resume;
PostThreadMessage(T1.ThreadID, WM_USER + 1, 0, 0);
Dennis I. Komarov (2012-07-31 22:40:00) [10]
> положительно скажется на сквозной производительности программы)
... и не только этой программы, а и общего самочувствия ос
Сергей М. (2012-07-31 16:23:00) [11]А уж раз он быстро проснулся при событии, то он и обслужит его быстрее, что в конечном итоге положительно скажется на сквозной производительности программы)
Сергей М. (2012-07-31 16:21:00) [12]
> не надо, и так достаточно.
Да зачем же вхолостую размандаривать кванты доступного потоку драгоценного времени ?
Ведь за то время, пока поток находится в kernel-time, он в состоянии не только тупо и беспробудно спать, но и быть готовым немедленно проснуться при наступлении интересующего его события)
AV (2012-07-31 15:37:00) [13]а, в этом смысле..
да, почему.. пойдет
тока не надо, и так достаточно.
+ я так лучше понимаю :)
Anatoly Podgoretsky (2012-07-31 12:56:00) [14]> AV (31.07.2012 12:51:05) [5]
Sleep пойдет, а WaitFor не пойдет, странно это
AV (2012-07-31 12:51:00) [15]
> Использовать функции Wait с таймаутом в одну секунду
не пойдет
это же только пример, реальность несколько другая :)
Anatoly Podgoretsky (2012-07-31 12:11:00) [16]Использовать функции Wait с таймаутом в одну секунду
AV (2012-07-31 11:58:00) [17]Понял. Спасибо!
Сергей М. (2012-07-31 11:43:00) [18]Логика ожидания/выборки/диспетчеризации/обработки сообщений в теле Execute может быть произвольной в пределах полного понимания происходящего - здесь полный простор для фантазии.
Единственные замечаня:
1. слип аж на 2 сек - это ж ни в какую Красную армию не вписывается.
Бестолковая трата драгоценного времени)
while not Terminated do
if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
begin
//TranslateMessage(Msg); // это нафих не нужно если поток не занимается обработкой сообщений клавиатурного ввода
DispatchMessage(Msg); // иногда удобней реализовать диспетчеризацию с использованием метода TObject.Dispatch()
end
else
Sleep(1);
или вариант с ожиданием/выборкой сообщений в kernel-mode:
while not Terminated and GetMessage(Msg, 0,0,0) do
DispatchMessage(Msg); // или Dispatch(msg.Message)
// в обработчике WM_QUIT выставить Terminated = True для выхода из цикла, WM_QUIT посылать из перекрытого деструктора перед вызовом inherited Destroy
2.
T1 := TMyTH.Create(false);
while not PostThreadMessage(T1.ThreadID, WM_USER, 0, 0) do Sleep(0);
//цикл-пустышка нужен для получения гарантии того что последующие отправляемые потоку сообщения
// не уйдут в пустоту, ибо очередь сообщений потока создается не раньше самого первого вызова им Wait/Get/PeekMessage()
AV (2012-07-31 11:27:00) [19]Что смущает
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644943%28v=vs.85%29.aspx
>> Applies to: desktop apps only
а если планируется в сервисе?