![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Синхронизация через SendMessage [D2005, XP]
Alex4445 © (2015-12-15 22:37:00)
type
TMyForm = class (TForm)
...
procedure SyncMsg (var T : TMessage); message WM_USER + 1;
end
var
MyForm : TMyForm;
procedure TMyForm.SyncMsg (var T : TMessage);
begin
CSL.Send ('Enter'); // CodeSiteLogger - система логгирования
sleep (2000);
CSL.Send ('Leave');
end;
TMyThread = class (TThread)
procedure Execute; override;
end;
procedure TMyThread.Execute;
begin
while (not Terminated) do
SendMessage (MyForm.Handle,WM_USER+1,0,0);
sleep (100);
end;
end;
Создается несколько однотипных потоков, которые через SendMessage выполняют определенный код (в данному случае лог + слип) в главном потоке.
Ожидаю увидеть в логе:
Enter
Leave
Enter
Leave
...
Enter
Leave
...
Т.е главный поток обрабатывает SendMessage-ы последовательно.
Вижу
Enter
Leave
Enter // ???
Enter // ???
Leave
Enter
Leave
...
Как такое получается? Как начал выполняться последующий SendMesssage пока не завершился предыдущий?
Или это "обман" связанный с работой логгера ?
Alex4445 (2015-12-16 13:02:00) [41]
procedure TMyThread.Execute;
begin
while (not Terminated) do
FCS.Enter; // TCriticalSection
SendMessage (MyForm.Handle,WM_USER+1,0,0);
FCS.Leave;
sleep (100);
end;
end;
Вот такой код должен быть?
Разве сам SendMessage - не гарантирует синхронизации ???
Rouse_ (2015-12-16 12:10:00) [42]А стоп, да затупил - Коля прав, не прочитал про множественные вызовы.
Да, вызов из второй нити приостановит выполнение кода из первой, поэтому в данном случае критсекция нужна
Alex4445 (2015-12-16 12:02:00) [43]
> вряд ли. SendMessage немедленное выполнение, без очереди,
> код процедуры не заблокирован, критической секции нет.
> ничего не мешает второму потоку вызвать свой SendMessage
> в момент когда первый на sleep-е. sleep в принципе и нужен
> чтобы "притушить" выполнение текущего, и дать "подышать"
> другим потокам. вот они и пользуются. это же фактически
> прямой вызов кода, все одно, что функцию описанную прямо
> в потоке (или неважно
> имхо, для логера нужен отдельный поток
где) вызвать.
> поменяй на PostMessage, очередь событий должна исправить
> ситуацию.
Хмм.. как это "без очереди"?
И Send и Post через очередь сообщений, отличие Send.. от Post.. что первый ждет завершения, а второй - нет.
> а посчитай количество Enter-ов и Leave. первых случаем не
> больше?
Нет. Все как нужно.
sniknik (2015-12-16 01:45:00) [44]> синхронизация на первый взгляд валидная
вряд ли. SendMessage немедленное выполнение, без очереди, код процедуры не заблокирован, критической секции нет. ничего не мешает второму потоку вызвать свой SendMessage в момент когда первый на sleep-е. sleep в принципе и нужен чтобы "притушить" выполнение текущего, и дать "подышать" другим потокам. вот они и пользуются. это же фактически прямой вызов кода, все одно, что функцию описанную прямо в потоке (или неважно где) вызвать.
поменяй на PostMessage, очередь событий должна исправить ситуацию.
или
+, еще вариант
> Как такое получается?
а посчитай количество Enter-ов и Leave. первых случаем не больше? в смысле может быть приходит "паразитное", забытое сообщение из другого места с тем же кодом?
имхо, для логера нужен отдельный поток + PostThreadMessage, а не основной c событием на форму.
Rouse_ (2015-12-16 00:03:00) [45]Скорее логер, синхронизация на первый взгляд валидная