![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
SendMessage & TThread [D6]
axx © (2004-12-16 14:06:00)Подскажите коректно ли использование SendMessage в главную форму из TThread. В моем случае я использую параметр Message'a для ведения логов в файле те
procedure TThread.SetError
(SendMessage(Form1.Handle,MY_MESSAGE,1,DWORD(Pchar('.........')));
procedure TForm1.MessageReceiver(var msg: TMessage);
begin
AddToLog(StrPas(PChar(msg.lParam))); //пишет в файл строку с ошибкой
msg.Result:=1;
end;
Digitman (2004-12-17 09:13:00) [1]в случае с асинхронными сообщениями (Post[Thread]Message) не самым худшим решением будет передача параметром таких сообщений интерфейсных ссылок
например :
- передатчик
var intf: IMyIntf;
..
intf := TMyObj.Create as IMyIntf;
try
intf._AddRef;
try
Win32Check(Post[Thread]Message(target, MESSAGE_CODE, Pointer(intf), 0));
except
intf._Release;
raise;
end;
finally
intf := nil;
end;
- приемник
var
intf: IMyIntf;
Msg: TMsg;
..
if PeekMessage(Msg, target, MESSAGE_CODE, MESSAGE_CODE, PM_REMOVE) then
intf := IMyIntf(Pointer(Msg.wParam));
try
.. работаем с intf
finally
intf := nil;
end;
и при завершении работы приемника во избежание мемликов "чистим" очередь от необработанных на этот момент MESSAGE_CODE-сообщений:
while PeekMessage(Msg, target, MESSAGE_CODE, MESSAGE_CODE, PM_REMOVE) do
IMyIntf(Pointer(Msg.wParam))._Release;
Ihor Osov'yak (2004-12-17 03:45:00) [2]2 Alex Konshin ©
Спасибо. Общая идея понятна..
> У тебя может быть ошибка при использовании PeekMessage (даже и не в твоем коде).
Пару дней назад искал глюк на ровном месте.. Многопоточное приложение, в потоке чего-то там делается, есть цыкл выборки сообщений. Для управения потоком извне в него посылаются сообщения. Из-за лени ради решил для экономии не создавать служебного окна и управляющие сообщения слать прямо потоку. Все нормально. Приложение работает круглосуточно, но раз на пол-дня такое впечатление, что какое-то управляющее сообщение не обрабатывается.. Страдал почти сутки.. Попробуй поймать баг, если он происходит раз в полдня.. И непредсказуемо. Потом появилась версия. Я там иногда обращался к стороннему COM-обьекту, исходников которого у меня естественно не было.. Предположил, что разработчик этого объекта мог у себя делать маленький циклы ожидания посредством закручивания альтернативного цикла выборки сообщений. И усе. Там наверное мои сообщения потоку и могли теряться..
С оконными ничего бы плохого не случилось, так как все же DispatchMessage упустить - все же нужно постараться.. Окошко все же служебное писать не стал, сделал все же эхо-ответ на сообщение как квитанцию, благо архитектура решения позволяла..
А через пару дней правдами и неправдами раздобыл исходник того COM - таки да, цикл задержки присутствует... :-(.
Да, возвращаясь к нашей теме - для неэкстремальных случаев, и когда отсутсвуют всякие финты в циклах выборки можно считать, что сообщения все же не теряются. Как и должно быть теоритически.
> более предпочтительно использовать SendMessageCallback,
Хм. Интересно. Как то раньше не использовал такую технику. Нужно принять во внимание. Еще раз спасибо.
Alex Konshin (2004-12-17 03:08:00) [3]Кстати, более предпочтительно использовать SendMessageCallback, там хоть выделение и отдача памяти будет в одном месте.
Alex Konshin (2004-12-17 03:00:00) [4]Теоретически ты можешь удалять сообщения. У тебя может быть ошибка при использовании PeekMessage (даже и не в твоем коде). То есть теоретически даже без глюков системы такое возможно и отловить это чрезвычайно трудно. Второй важный момент (как раз-таки очень вероятный для исходной задачи): мы легко можем забить очередь сообщений и приложение просто повиснет. Вывод в лог вполне может генерировать сотни миллионов сообщений в секунду, я не уверен, что при таком повороте событий приложение будет работать корректно. Что например, делать посылающей нити, если PostMessage будет неуспешным?
Вот сейчас я делаю эмулятор процессора SuperH-4, так он легко выполняет 10 миллионов операций в секунду и более. Теперь представь, что будет, если я захочу их трассировать, да еще и с подробностями? Например, при выводе трассы через OutputDebugString программа DebugView надолго уходила в аут. Когда я делал свой лог я даже и не думал делать это через PostMessage.
Ihor Osov'yak (2004-12-17 02:41:00) [5]2 [2] Alex Konshin © (17.12.04 02:23)
> т.к. message может потеряться (не должно, но может),
Вот-вот... Постоянно такое слышу.. А практически это происходит? Удавалось ли кому нибуть такое наблюдать? Если происходит, то что такой поворот сюжета провоцирует?
Зы. Всякие аварийные снятия нитей и процессов не рассматриваем..
Зы2. Ну и слабодокументированные фишки на пример того, что в очереди может находится не более одного сообщения от таймера тоже игнорируем..
Alex Konshin (2004-12-17 02:23:00) [6]Использовать-то корректно, только твоя нить по SendMessage будет ждать до тех пор, пока основная нить (где бежит VCL) не обработает его. Но и PostMessage в твоем варианте использовать нельзя, т.к. ты отсылаешь УКАЗАТЕЛЬ на место в памяти, где в этот момент находится строка, нить же будет проболжать бежать и может использовать ту же область памяти для других нужд.
Т.е. по уму нужно
- либо самому организовывать очередь FIFO и сообщать основной нити лишь о самом факте добавления сообщения в очередь;
- либо самому выделять память, копировать туда содержимое строки и в message передавать указатель на нее, а принимающий должен будет освободить память.
Второй вариант чреват memory leaks, т.к. message может потеряться (не должно, но может), и не будет и сообщения в логе, и ссылка на память потетяется.
Игорь Шевченко (2004-12-16 14:08:00) [7]
> коректно ли использование SendMessage в главную форму из
> TThread
Корректно.
С уважением,