Fil Système de messagerie sûr, asynchrone et simpliste pour la communication entre les classes / couches de Delphi créé par l'équipe IPUB.
Delphi a son propre système de messagerie (System.Messaging.pas) qui fonctionne bien mais qui est totalement synchrone et en forme de filetage. Dans les systèmes multithread, nous devons toujours communiquer avec d'autres classes, parfois de manière synchrone, parfois de manière asynchrone, de synchroniser parfois avec le mainthread (dans le cas de l'interface utilisateur), et le faire sans système de messages (communiquer directement) rend le code grand et complexe, sujet à de nombreux bogues.
Un système de messagerie idéal serait un système sûr de fil qui permettrait à un cours de s'abonner, puis de se désabonner pour écouter un message particulier au cours de cette fois, et cette classe d'écoute qui recevra le message est de savoir qui informera comment l'expéditeur invoquera sa méthode: sur le même fil ( publication ), sur le thread principal ( principal ), sur un autre thread ( Async ) et sur un fil autre que principal ( arrière-plan ). C'est la base de notre système de messagerie, l'utilisation est similaire à un autre système existant, le bus d'événement Delphi (DEB).
Voir la comparaison dans un environnement avec 1000 objets:
| S'abonner | Poste | Se désabonner | |
|---|---|---|---|
| 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 ;Tout d'abord, vous devez vous abonner à votre classe pour écouter des messages, puis toutes les méthodes publiques qui ont l'attribut [abonner] seront abonnées.
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 ;Vous pouvez également déclarer la méthode dans une partie protégée, mais pour ce faire, vous devez ajouter {$ rtti explicit méthodes ([vcprotected, vcpublic, vcpublished])} avant le cours.
var
LMessage: ILogOutMessage
begin
LMessage := TLogOutMessage.Create;
GMessaging.Post(LMessage);Dans les exemples précédents, nous avons montré un message d'interface, mais il y a tout à fait 3 types de messages:
| Identité | Paramètre |
|---|---|
| nom (explicite) | chaîne |
| Guide de l'interface des paramètres (implicite) | interface |
| Guide de l'interface des paramètres (implicite) + nom (explicite) | interface |
Pour recevoir des messages avec l'identité du nom, déclarez simplement le nom dans l'attribut de méthode:
[Subscribe( ' Name ' , TipMessagingThread.Main)]Pour envoyer des messages avec l'identité du nom, informez-le simplement dans l'appel du post:
GMessaging.Post( ' Name ' , LMessage);Remarque: le nom explicite est insensible à la casse.
Dans l'attribut [abonner], vous pouvez déterminer comment la méthode recevant un message sera exécutée:
| Gentil | Description |
|---|---|
| TipMessagthread.Posting | La valeur par défaut, la méthode d'abonné sera invoquée dans le même fil de publication où le post a été appelé |
| TipMessagthread.main | La méthode de l'abonné sera invoquée dans le fil principal |
| TipMessagthread.async | La méthode de l'abonné sera invoquée de manière asynchrone dans un nouveau fil annonnymous autre que le fil de publication |
| TipMessagthread.background | Si le thread de publication est le thread principal, la méthode de l'abonné sera invoquée de manière asynchrone dans un nouveau fil annonnymous, autre que le thread de publication. Si le thread de publication n'est pas le thread principal, la méthode d'abonnée sera invoquée de manière synchrone dans le même fil de publication |
Bien que l'utilisation de l'attribut [abonnez-vous] pour abonner une méthode soit très pratique, elle est limitée car vous devez définir le nom du message avant compilation, en temps de conception, et parfois il est vraiment utile de définir le nom des messages dans l'exécution. Un exemple, un message pour un produit qui a été modifié `` Product_105346_changed '', ce nom de ce message que je ne peux définir qu'à l'heure d'exécution, nous avons donc ajouté l'option pour vous abonner / désabonner une méthode pour écouter un message manuellement:
GMessaging.SubscribeMethod<string>( ' product_105346_changed ' , Self.OnProductChanged, TipMessagingThread.Posting);
GMessaging.UnsubscribeMethod<string>( ' product_105346_changed ' , Self.OnProductChanged);Ces deux méthodes manuelles sont indépendantes des méthodes d'abonnement / désabonnement. Vous pouvez fusionner la même classe avec des méthodes souscrites automatiquement à l'aide de l'attribut [abonner] et appeler abonner / désabonner, et en même temps dans cette classe ayant des méthodes que vous avez ajoutées manuellement à l'aide d'abonnement / non-subscription.
Un autre avantage des méthodes d'inscription manuelle est qu'ils ne se limitent pas uniquement aux méthodes publiques (bien que ce problème puisse être résolu en utilisant la directive RTTI Explicit Methods).
L'idée du système est simplement de transmettre des messages, des notifications, des informations contenant ou non, alors gardez à l'esprit qu'il n'est pas conseillé de placer de grands codes ou codes avec des arrêts (attente) dans les méthodes souscrites pour écouter des messages, car cela affecterait directement les performances du système, même dans les modes asynchrones.
Une autre considération n'est qu'un rappel de la bonne façon d'utiliser le ttask de Delphi. N'utilisez jamais TTASK pour exécuter des méthodes avec des arrêts (événements, sémaphores, ...), il n'a pas été fait pour cela, son objectif est d'effectuer des tâches continues et plus simples, si votre tâche est plus complexe, la bonne chose est d'utiliser un Tthread. Nous vous avertissons à ce sujet, car notre système utilise le TTASK de Delphi pour augmenter les performances principalement dans des environnements plus complexes en plus de enregistrer les ressources, et si vous utilisez ttask incorrectement dans vos codes, vous pouvez faire geler votre application lors de l'envoi d'un message.
La messagerie IPUB est sous licence dans le MIT et le fichier de licence est inclus dans ce dossier.