![]() |
Synchronisierung asynchroner Kommunikation über Messages
Hi,
ich versuche gerade zwei Fenster, die über Messages miteinander kommunizieren, zu synchronisieren. Damit meine ich folgendes: Meine Anwendung schickt die Message "GET CALL xx PARTNER_HANDLE" an die andere Anwendung und diese sendet darauf (asynchron) die Antwort "CALL xx PARTNER_HANDLE yyyyyyy". Mein Problem besteht nun darin, eine Funktion
Delphi-Quellcode:
zu bauen, die synchron ein Ergebnis zurückliefert. Die Funktion müsste also so lange warten, bis das Ergebnis vorliegt.
function GetPartnerhandle(Call: Integer): String
Hier ist mal mein Idee:
Delphi-Quellcode:
Leider bleibt meine Anwendung offenbar in der repeat-Schleife stecken, d.h. die Abbruchbedingung tritt nie ein. Mit anderen Worten: die Variable LastMsg, die sonst immer die zuletzt erheltene Message enthält, bleibt unverändert und daraus schließe ich, dass die Messages trotz "Application.ProcessMessages;" nicht mehr verarbeitet werden. ...warum nur?
function MyClass.GetPartnerhandle(Call: Integer): String;
begin // SendMsg sendet die Message an die andere Anwendung. Self.SendMsg('GET CALL ' + IntToStr(Call) + ' PARTNER_HANDLE'); repeat Sleep(50); Application.ProcessMessages; // LastMsg ist eine String-Variable, die immer die zuletzt erhaltene Message enthält. until (Pos('CALL ' + IntToStr(Call) + ' PARTNER_HANDLE', Self.LastMsg) > 0) or Application.Terminated; Result := Copy(Self.LastMsg, Pos('PARTNER_HANDLE', Self.LastMsg) + 15, 255); end; |
Re: Synchronisierung asynchroner Kommunikation über Messages
Hi,
nun ja mit sleep legst du nun mal den ganzen Prozess schlafen. Das heißt natürlich auch, dass in der Zeit weder eine Message verarbeitet wird, noch dürfte sie empfangen werden. Ich weiß natürlich nicht, um was für eine Art von Kommunikation es sich bei dir handelt, aber sieht auch nicht sehr Threadsafe aus. Würdest du auf CALL 1 und CALL 2 warten und 2 kommt kurz nach 1, könnte es sein, dass du 1 nie siehst oder ein falsches Ergebnis in 1 kopierst. Aber das ist eine andere Sache. Definier dir ein Ereignis, dass speziell für das empfangen von einer Nachricht zuständig ist (ein Nachfahre von TEvent). Dann kannst du deine Schleife durch ein NachfahreVonTEvent.WaitFor(TimeOut) ersetzen. Dieses liefert dir dann entweder ein Timeout oder dass ein Signal empfangen wurde. Um das Signal zu senden, einfach NachfahreVonTEvent.setEvent aufrufen. (beide male als Instanz zu verstehen) Hoffe das hilft, Gruß Der Unwissende |
Re: Synchronisierung asynchroner Kommunikation über Messages
Danke für deine Ratschläge, aber es will immernoch nicht funktionieren.
Meine Funktion sieht jetzt vorläufig in etwa so aus:
Delphi-Quellcode:
FMsgEvent ist ein TEvent, dass immer ausgelöst wird (mit SetEvent), wenn eine neue Message der anderen Anwendung reinkommt. Es handelt sich übrigens um WM_COPYDATA-Nachrichten und die Prozedur, die diese entgegennimmt und daraufhin das Event auslöst, befindet sich in derselben Klasse (MyClass). Könnte es sein, dass der WaitFor-Aufruf die ganze Klasseninstanz lahmlegt, sodass auch keine Messages mehr entgegengenommen werden können?
function MyClass.GetPartnerHandle(Call: Integer): String;
begin Self.SendMsg('GET CALL ' + IntToStr(Call) + ' PARTNER_HANDLE'); repeat Self.FMsgEvent.WaitFor(INFINITE); until (Pos('CALL ' + IntToStr(Call) + ' PARTNER_HANDLE', Self.FLastMsg) > 0); Result := Copy(Self.FLastMsg, Pos('PARTNER_HANDLE', Self.FLastMsg) + 15, 255); end; |
Re: Synchronisierung asynchroner Kommunikation über Messages
Guten Morgen, oXmoX.
Durch das Einstellen einer WM_COPYDATA Nachricht in die message queue der Anwendung A durch die Anwendung B kommt doch schon eine Kommunikation zwischen den Anwendungen zu Stande - wozu dann noch eine Kommunikation über kernel objects? Echtzeit-Verarbeitung lässt sich durch die Verknüpfung der Techniken wohl nicht erreichen, da es passieren kann, dass die Nachricht WM_COPYDATA noch unbearbeitet in der queue steht, nachdem das event object in den signalled state versetzt wurde. Außerdem macht die REPEAT-Schleife beim Warten keinen Sinn. Entweder du wartest INFINITE ohne Schleife oder du wartest mit TIMEOUT und Schleife. Im main thread ist das aber aus meiner Sicht eher ungeschickt. Wenn du mit kernel objects zur Prozess-Synchronisierung arbeitest, dann solltest du auch threads benutzen, damit das Konzept richtig zum tragen kommt. Ich würde die Nachricht WM_COPYDATA im main thread verarbeiten. Wenn die Verarbeitung der übermittelten Daten eine Nebenläufigkeit bedingt, dann würde ich einen speziellen thread für diese Aufgabe einrichten, der dann aber auch über seine Methoden gesteuert werden kann. Theoretische Grüße vom marabu |
Re: Synchronisierung asynchroner Kommunikation über Messages
Hallo marabu!
Zitat:
Ich arbeite zum ersten Mal mit Messages und auch mit Nebenläufigkeiten. Also sagt mir bitte bescheid, wenn ich da was falsch sehe. Kann man das so Umsetzen? Ist es möglich, einen Thread zu bauen, der völlig unabhängig vom Main-Thread Messages empfangen kann? Bin für jede Hilfe dankbar! Gruß, oXmoX |
Re: Synchronisierung asynchroner Kommunikation über Messages
Da ist ein Denkfehler in deinen Überlegungen. Du darfst den main thread nie schlafen legen. Der ist für die Benutzerschnittstelle zuständig - und beinhaltet die message pump. Allerdings kannst du jederzeit Teile der Benutzerschnittstelle deaktivieren, wenn der Programmzustand das erforderlich macht.
Ich würde also die Nachrichten im main thread verarbeiten, und die eigentliche Arbeit von speziellen threads erledigen lassen, die ich nach dem Empfang bestimmter Nachrichten starte. Die Vorgehensweise wäre damit genau das Gegenteil zu deinen eigenen Überlegungen, aber auch so erreichst du eine Synchronisierung. marabu |
Re: Synchronisierung asynchroner Kommunikation über Messages
Zitat:
Ist es auf diese Weise Möglich, die GetPartnerhandleMethode als Funktion zu realisieren, die nach Ihrem Aufruf direkt das Anfrageergebnis zurückliefert? ...Ich zweifle irgenwie noch dran. ...Vermutlich hab ich dich nicht richtig verstanden. Ich schätze ich sollte mich jetzt erstmal noch ein wenig mit Threads beschäftigen. Wie gesagt: ist Neuland für mich. |
Re: Synchronisierung asynchroner Kommunikation über Messages
Wenig bekannt ist, das sich auch WM_SETTINGSCHANGE aka WM_WININICHANGE zum Versenden eines Strings eignet.
Man muss die Message nur gezielt versenden, statt sie zu broadcasten und man sollte sie im OnMessage ausfiltern, damit sich nicht einige Komponenten bemuessigt fuehlen ihre Systemdefaults neu einzulesen. Das erlaubt es WM_COPYDATA freizuhalten fuer andere Zwecke. |
Re: Synchronisierung asynchroner Kommunikation über Messages
Zitat:
Zitat:
Freundliche Grüße vom marabu |
Re: Synchronisierung asynchroner Kommunikation über Messages
Wenn du mit WaitFor auf einen Event wartest, dann legst du natürlich den ganzen Thread lahm. Es werden also auch keine Messages verarbeitet.
Ohne den Inhalt von Self.SendMsg zu kennen, tue ich mir allerdings recht schwer, dir einen guten Tip zu geben. Es gibt nämlich ganz verschiedene Funktionen, um eine Message an eine andere Anwendung zu verschicken. Je nachdem welche du verwendest, mußt du auch dementsprechend dein Programm anpassen... |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:55 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz