У меня есть небольшое клиент-серверное приложение, где сервер отправляет некоторые сообщения клиенту с использованием именованных каналов. Клиент имеет два потока - основной поток графического интерфейса и один «принимающий поток», который продолжает получать сообщения, отправленные сервером через именованный канал. Теперь, когда какое-либо сообщение получено, я хотел бы запустить настраиваемое событие - однако это событие должно обрабатываться не на вызывающем потоке, а в главном потоке графического интерфейса - и я не знаю, как это сделать (и это даже возможно).Delphi - обработка событий с перекрестными потоками
Вот что я до сих пор:
tMyMessage = record
mode: byte;
//...some other fields...
end;
TMsgRcvdEvent = procedure(Sender: TObject; Msg: tMyMessage) of object;
TReceivingThread = class(TThread)
private
FOnMsgRcvd: TMsgRcvdEvent;
//...some other members, not important here...
protected
procedure MsgRcvd(Msg: tMyMessage); dynamic;
procedure Execute; override;
public
property OnMsgRcvd: TMsgRcvdEvent read FOnMsgRcvd write FOnMsgRcvd;
//...some other methods, not important here...
end;
procedure TReceivingThread.MsgRcvd(Msg: tMyMessage);
begin
if Assigned(FOnMsgRcvd) then FOnMsgRcvd(self, Msg);
end;
procedure TReceivingThread.Execute;
var Msg: tMyMessage
begin
//.....
while not Terminated do begin //main thread loop
//.....
if (msgReceived) then begin
//message was received and now is contained in Msg variable
//fire OnMsgRcvdEvent and pass it the received message as parameter
MsgRcvd(Msg);
end;
//.....
end; //end main thread loop
//.....
end;
Теперь я хотел бы быть в состоянии создать обработчик событий в качестве члена класса TForm1, например
procedure TForm1.MessageReceived(Sender: TObject; Msg: tMyMessage);
begin
//some code
end;
, что не было бы выполненных в принимающем потоке, но в основном потоке пользовательского интерфейса. Мне особенно нравится, что принимающий поток просто запускает событие и продолжает выполнение, не дожидаясь возврата метода обработчика событий (в основном мне понадобится что-то вроде метода .NET Control.BeginInvoke)
Я действительно начинаю в это (я пытался научиться определять пользовательские события всего несколько часов назад.), поэтому я не знаю, возможно ли это, или если я что-то делаю неправильно, так что заблаговременно большое спасибо за вашу помощь.
Ugh. Синхронизация останавливает все второстепенные потоки и выполняется в контексте основного потока, что означает, что он сильно нарушает назначение нескольких потоков в первую очередь. Есть TONS лучших способов, чем Synchronize. Однако я не голосую за вас, потому что, хотя это ужасный ответ, это технически обоснованный вариант. :-) –
Кто вам сказал этот миф? Синхронизация не блокирует «все» вторичные потоки. Он только блокирует поток, из которого он был вызван, и это происходит из-за его синхронного характера. Но другие потоки продолжают работать. –
Да только заблокирован вызывающий поток. Это не лучший механизм, но если вы знаете, как это работает, вы должны быть в порядке. – Runner