Thread Safe, Asynchronous und Simple Messaging System für die Kommunikation zwischen Klassen / Ebenen in Delphi, die vom IPUB -Team erstellt wurden.
Delphi hat ein eigenes Messaging -System (System.Messaging.pas), das gut funktioniert, aber vollständig synchron und fadenunabhängig ist. In Multithread -Systemen müssen wir immer mit anderen Klassen kommunizieren, manchmal synchron, manchmal asynchron, manchmal synchronisiert mit dem Maintread (im Fall der Benutzeroberfläche) und macht dies ohne ein Nachrichtensystem (direkt kommunizieren) den Code groß und komplex, anfällig zu vielen Fehler.
Ein ideales Messaging -System wäre ein Thread -Safe -System, mit dem eine Klasse in dieser Zeit eine bestimmte Nachricht anhören und sich dann abmelden würde, und diese Hörerklasse, die die Nachricht empfängt, ist, wer informiert, wie der Absender seine Methode aufgerichtet hat: Auf demselben Thread ( Posting ), im Haupt -Thread ( Main ), auf einem anderen Thread ( Async ) und auf einem anderen Thread ( im Hintergrund ). Dies ist die Grundlage für unser Messaging -System, die Verwendung ähnelt einem anderen vorhandenen System, dem Delphi Event Bus (DEB).
Siehe den Vergleich in einer Umgebung mit 1000 Objekten:
| Abonnieren | Post | Abbestellen | |
|---|---|---|---|
| IPUB | 1,6368 ms | 0,1215 ms | 1,7666 ms |
| Deb | 9.8832 ms | 2,0293 ms | 4.0022 ms |
ILogOutMessage = interface
[ ' {CA101646-B801-433D-B31A-ADF7F31AC59E} ' ]
// here you can put any data
end ;Zunächst müssen Sie Ihre Klasse abonnieren, um Nachrichten anzuhören, und dann alle öffentlichen Methoden, die das [abonnement] -attribut haben, werden abonniert.
TForm1 = class (TForm)
procedure FormCreate (Sender: TObject);
procedure FormDestroy (Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
[Subscribe(TipMessagingThread.Main)]
procedure OnLogout ( const AMessage: ILogOutMessage);
end ;
...
procedure TForm1.FormCreate (Sender: TObject);
begin
GMessaging.Subscribe(Self);
end ;
procedure TForm1.FormDestroy (Sender: TObject);
begin
GMessaging.Unsubscribe(Self);
end ;
procedure TForm1.OnLogout ( const AMessage: ILogOutMessage);
begin
Showmessage( ' Log out! ' );
end ;Sie können die Methode auch im geschützten Teil deklarieren. Dazu müssen Sie jedoch {$ rtti explizite Methoden ([VCProtected, VCPublic, VCPublished])} vor der Klasse hinzufügen.
var
LMessage: ILogOutMessage
begin
LMessage := TLogOutMessage.Create;
GMessaging.Post(LMessage);In den vorherigen Beispielen haben wir eine Schnittstellenmeldung gezeigt, aber es gibt insgesamt 3 Meldungen:
| Identität | Parameter |
|---|---|
| Name (explizit) | Saite |
| GUID der Parameterschnittstelle (implizit) | Schnittstelle |
| GUID der Parameterschnittstelle (implizit) + Name (explizit) | Schnittstelle |
Um Nachrichten mit Namen Identität zu empfangen, deklarieren Sie einfach den Namen in der Methode -Attribut:
[Subscribe( ' Name ' , TipMessagingThread.Main)]Um Nachrichten mit Namensidentität zu senden, informieren Sie sie einfach im Post -Anruf:
GMessaging.Post( ' Name ' , LMessage);HINWEIS: Der explizite Name ist Fall-unempfindlich.
Im Attribut [abonnieren] können Sie bestimmen, wie die Methode, die eine Nachricht empfängt, ausgeführt wird:
| Art | Beschreibung |
|---|---|
| TipMessagingThread.Posting | Der Standard, die Abonnentenmethode wird im selben Post -Thread aufgerufen, in dem Post aufgerufen wurde |
| TipMessagingThread.main | Die Abonnentenmethode wird im Haupt -Thread aufgerufen |
| TipMessagingThread.async | Die Abonnentenmethode wird asynchron in einem neuen anonnymischen Faden als dem Posting -Thread aufgerufen |
| TipMessagingThread.background | Wenn der Posting -Thread der Haupt -Thread ist, wird die Abonnentenmethode asynchron in einem neuen anonnymen Thread als dem Posting -Thread aufgerufen. Wenn der Posting -Thread nicht der Haupt -Thread ist, wird die Abonnentenmethode synchron im selben Posting -Thread aufgerufen |
Obwohl die Verwendung des [abonnierten] Attributs zum Abonnieren einer Methode sehr praktisch ist, ist es begrenzt, da Sie den Namen der Nachricht vor der Kompilierung in der Designzeit definieren müssen, und manchmal ist es wirklich nützlich, den Namen der Nachrichten in Laufzeit zu definieren. Ein Beispiel, eine Nachricht für ein Produkt, das "product_105346_changed" geändert wurde, dieser Name dieser Nachricht, die ich nur zum Laufzeit definieren kann. Daher haben wir die Option hinzugefügt, eine Methode zum Anhören einer Nachricht manuell zu abonnieren / abzuschreiben:
GMessaging.SubscribeMethod<string>( ' product_105346_changed ' , Self.OnProductChanged, TipMessagingThread.Posting);
GMessaging.UnsubscribeMethod<string>( ' product_105346_changed ' , Self.OnProductChanged);Diese beiden manuellen Methoden sind unabhängig von den Abonnement- / Abzweigmethoden. Sie können dieselbe Klasse mit abonnierten Methoden automatisch mit dem Attribut [abonnieren] und abonnieren / abmelden und gleichzeitig in dieser Klasse mit Methoden, die Sie manuell anhand von Abonnemethod / Unsubscribemethod hinzugefügt haben, mithilfe von Methoden fusionieren.
Ein weiterer Vorteil von manuell anmelden Methoden besteht darin, dass sie nicht nur auf öffentliche Methoden einschränken (obwohl dieses Problem mit der Richtlinie der RTTI Expliziten Methoden gelöst werden kann).
Die Idee des Systems besteht nur darin, Nachrichten zu leiten, Mitteilungen zu leiten, die Informationen enthalten oder nicht. Beachten Sie daher, dass es nicht ratsam ist, große Codes oder Codes mit Stopps (Wait For) innerhalb der abonnierten Methoden zum Anhören von Nachrichten zu platzieren, da dies die Leistung des Systems auch in asynchronen Modi direkt beeinflussen würde.
Eine weitere Überlegung ist nur eine Erinnerung an die richtige Art, Delphis TTask zu verwenden. Verwenden Sie niemals TTask, um Methoden mit Stopps (Ereignisse, Semaphoren, ...) auszuführen. Es wurde nicht dafür gemacht. Sein Ziel ist es, kontinuierliche und einfachere Aufgaben auszuführen. Wenn Ihre Aufgabe komplexer ist, ist es die richtige Sache, ein Thread zu verwenden. Wir warnen Sie davor, da unser System das TTask von Delphi verwendet, um die Leistung hauptsächlich in komplexeren Umgebungen zusätzlich zum Speichern von Ressourcen zu erhöhen. Wenn Sie TTask in Ihren Codes falsch verwenden, können Sie Ihre Anwendung beim Senden einer Nachricht einfrieren.
Die IPUB -Messaging ist unter MIT lizenziert und die Lizenzdatei ist in diesem Ordner enthalten.