線程安全,異步和簡單的消息傳遞系統,用於IPUB團隊創建的Delphi類 /層之間的交流。
Delphi擁有自己的消息傳遞系統(System.Messaging.PAS),可正常工作,但完全同步並且線程不安全。在多線程系統中,我們始終需要與其他類進行通信,有時是同步的,有時異步的,有時會與Mainthread(在UI的情況下)同步,並且在沒有消息系統的情況下進行此操作(直接直接通信)使代碼大而復雜,易於許多錯誤。
理想的消息傳遞系統將是一個線程安全系統,該系統將允許類訂閱,然後在這段時間內取消訂閱來收聽特定消息,而將接收到消息的偵聽器類是誰將告知發件人如何調用其方法:在同一線程(發布),在主線程( MAIN )上,在另一個線程( async )和其他主線(MAIN)和其他主(背景)。這是我們的消息傳遞系統的基礎,使用情況類似於另一個現有系統Delphi Event Bus(DEB)。
請參閱具有1000個對象的環境中的比較:
| 訂閱 | 郵政 | 退訂 | |
|---|---|---|---|
| IPUB | 1.6368毫秒 | 0.1215 ms | 1.7666 ms |
| Deb | 9.8832 ms | 2.0293 ms | 4.0022毫秒 |
ILogOutMessage = interface
[ ' {CA101646-B801-433D-B31A-ADF7F31AC59E} ' ]
// here you can put any data
end ;首先,您必須訂閱班級以收聽消息,然後將訂閱具有[subscribe]屬性的所有公共方法。
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 ;您還可以在受保護的部分中聲明該方法,但是要執行此操作,您需要在類之前添加{$ rtti顯式方法([[vcprotected,vcpublic,vcppublic,vcpublic,vcpublic)]})}。
var
LMessage: ILogOutMessage
begin
LMessage := TLogOutMessage.Create;
GMessaging.Post(LMessage);在前面的示例中,我們顯示了一個接口消息,但總共有3種類型的消息:
| 身份 | 範圍 |
|---|---|
| 名稱(明確) | 細繩 |
| 參數界面的GUID(隱式) | 介面 |
| 參數接口的GUID(隱式) +名稱(顯式) | 介面 |
要接收具有名稱身份的消息,只需在方法屬性中聲明名稱:
[Subscribe( ' Name ' , TipMessagingThread.Main)]要發送具有名稱身份的消息,只需在帖子通話中告知它:
GMessaging.Post( ' Name ' , LMessage);注意:顯式名稱對情況不敏感。
在[訂閱]屬性中,您可以確定如何執行接收消息的方法:
| 種類 | 描述 |
|---|---|
| tipMessagingThread.posting | 默認,訂戶方法將在稱為帖子的同一發佈線程中調用 |
| tipMessagingThread.main | 訂戶方法將在主線程中調用 |
| tipMessagingThread.Async | 訂戶方法將在新的無聲音線中異步調用,而不是發佈線程 |
| tipMessagingThread.background | 如果發佈線程是主螺紋,則除了發佈線程外,訂戶方法將在新的鼻螺紋中異步調用。如果發佈線程不是主線程,則將在同一發佈線程中同步調用訂戶方法 |
儘管使用[訂閱]屬性訂閱方法非常實用,但它是有限的,因為您必須在編譯之前定義消息的名稱,在設計時間內,有時在運行時定義消息的名稱確實很有用。一個示例,一個已更改為“ product_105346_changed”的產品的消息,該消息的名稱我只能在運行時定義,因此我們添加了選項以訂閱 /退訂手動收聽消息的方法:
GMessaging.SubscribeMethod<string>( ' product_105346_changed ' , Self.OnProductChanged, TipMessagingThread.Posting);
GMessaging.UnsubscribeMethod<string>( ' product_105346_changed ' , Self.OnProductChanged);這兩種手動方法與訂閱 /退訂方法無關。您可以使用[subscribe]屬性自動將同一類與訂閱方法合併,並調用subscribe / nisberscribe,與此同時,在此類的同時,使用sisscribemethod / unsemethod / unsubScribemeThod手動添加的方法。
手動註冊方法的另一個好處是,它們不僅限於公共方法(儘管可以使用RTTI顯式方法指令解決此問題)。
系統的想法僅是為了轉發消息,通知,包含信息或不信息,因此請記住,不建議將大型代碼或代碼放置在訂閱的方法中以聆聽消息的方式,因為這將直接影響系統的性能,即使以異端模式下也會影響系統的性能。
另一個考慮因素只是提醒使用Delphi的TTASK的正確方法。切勿使用TTASK執行停止(事件,信號量,...),它不是為此而進行的,其目標是執行連續,更簡單的任務,如果您的任務更為複雜,正確的方法是使用tthread。我們正在警告您,因為我們的系統使用Delphi的TTASK來提高性能,主要在更複雜的環境中除了節省資源之外,如果您在代碼中不正確地使用ttask,則在發送消息時可能會導致應用程序凍結。
IPUB消息傳遞在MIT下許可,並且該文件夾中包含許可證文件。