簡體   English   中英

動態向一組物體發射信號

[英]Emitting a signal to one object in a set dynamically

我遇到的情況是我有一個發射器對象和一組接收器。 接收器屬於同一類別,實際上代表一組相同類型的設備。 我正在使用Qt框架。

  • 發射器本身首先會收到一個信號,要求從其中一個設備獲取信息。

  • 在相應的插槽中,發射器必須檢查以查看哪些接收器已“就緒”,然后發送其自身的信號以向其中一個設備請求數據(以先准備好者為准)。

發射器非常快地接收信號,大約為毫秒。 我可以考慮通過三種方式僅從其中一台設備安全地請求數據(這些設備位於各自的線程中,因此我需要一種線程安全的機制)。 設備的數量不是靜態的,並且可以更改。 設備總數非常小(肯定在5-6以下)。

1)添加或刪除所有設備時,請連接它們。 發出一個請求,並讓設備對象自己使用某些特定的設備標簽過濾出該請求是否針對他們。 這種方法很好,因為執行檢查的請求插槽將在專用線程的上下文中執行,但隨着設備數量的增加而浪費。

2)需要發送請求時,即時連接發射器內的對象並與之斷開連接。

3)必要時使用QMetaObject :: invokeMethod()發送請求。

性能很重要。 有誰知道哪種方法是“最好的”,或者是否有更好的方法?

問候

普里斯

注意:需要說明的是:發射器從應用程序獲取信號,通過查詢設備獲取信息。 瘋狂的ASCII藝術去:

(app)<---->(發射器)<------>(接收器)<-|->物理設備

我在這里有趣的是多線程環境。

如果您被限制在Qt信號/插槽系統之間,則針對特定問題的答案:

1)絕對不是要走的路。 Emitter發出的事件總數等於Receivers數量的事件將排隊等待設備的線程事件循環,然后一旦線程到達這些事件,將發生相同數量的插槽調用。 即使大多數丟失的只是if(id!=m_id) return; 在他們的第一行中,它在Qt的核心中發生了大量事情。 將一個斷點放在Qt::QueuedConnection信號引起的插槽中,並在實際的堆棧跟蹤中進行驗證。 通常,它至少要從xyEventLoop::processEvents(...)進行至少4次調用,因此就時間而言,“僅返回”絕對不是“免費的”。

2)不確定Qt的內部實現實際上如何,但是據我所知,連接和斷開連接最有可能包括將發送方和接收方插入和刪除到某些列表中,這些列表很可能通過QMutex鎖定進行訪問。 -有時也可能是“昂貴的”,快速連接和斷開連接絕對不是最佳實踐。

3)可能是您發現仍在使用Qt的單槽系統的最“昂貴的按時”解決方案。

(可選)看看QSignalMapper 它完全按照您計划在選項1)中執行的操作而設計。

在您的Emitter ReceiversReceivers之間有更多的最佳通信解決方案,但是作為最佳實踐,我首先選擇最易於使用和快速實施的選項,但有可能會足夠快的運行時間(即選項3)。 )。 然后,完成后,查看它是否滿足您的性能要求。 如果不是,只有這樣,才考慮在數據提供者-數據使用者體系結構中將共享內存與互斥鎖一起使用( Emitter線程將請求數據快速發布到循環列表中,而Receiver線程在有時間的時候讀取它們,然后發布結果以類似的方式返回,而Emitter線程不斷輪詢完成的結果。)

根據您提供的信息,我仍然建議使用Reactor實施。 如果您不使用ACE,則可以實現自己的。 基本架構如下:

  1. 從應用程序接收到信號或數據時,請使用select喚醒。
  2. 如果發送列表上已准備好套接字,則只需選擇一個套接字並發送數據即可
  3. 發送數據后, Receiver會將自己從可用的套接字/處理程序集中刪除
  4. 處理數據后,接收方Reciever自己重新注冊到可用收件人列表中。

我之所以建議ACE是因為它具有Reactor模式的最簡單使用的實現之一。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM