2013-12-09 17 views
0

我有一個條件,在我的應用程序中有不明量的第三方線程調用回調。該回調在調用它的線程的上下文中發出一個信號。始終是相同的信號,但是在任何給定時刻有10個不同的線程可以發射它。Qt:如何從所有信號排隊的插槽中的多線程捕獲信號

我想排隊所有這些單身人士,並在我擁有的單個QThread的上下文中用適當的插槽對它們進行處理。

我該怎麼做?以下代碼不起作用。儘管我看到信號從不同的線程發出,但我的「On ...」從未被調用過。

QObject::connect(this,SIGNAL(ProcessQueuedOutEvent(int)), 
     this, 
     SLOT(OnProcessQueuedOutEvent(int)), 
     Qt::QueuedConnection); 
+0

Meh - 'OutEvent'是否帶有在回調中返回的輔助指針/ int,因此可用於傳遞上下文? –

+0

哦,我肯定會將緩衝區複製到我的插槽。我假設一旦函數返回,我得到的指針結構將被擦除。 – JasonGenX

+0

你的班級「這個」是一個QThread對象,你擁有QThread是什麼意思? – Kikohs

回答

0

請問你的QThread運行事件循環?它做它來接收信號:

排隊連接槽被調用時控制返回到接收器的線程的 事件循環。該插槽在 接收器的線程中執行。

基本上排隊連接的工作方式如下:

  1. 發起者發出的信號。
  2. Qt創建一個事件並將其發佈到接收者事件隊列中。
  3. 接收器通過它的事件隊列,拾取事件並將信號分配到連接的插槽中。

因此,如果您不運行事件隊列,則會發布信號,但您的線程將永遠不會收到它們。

所以基本上你的線程應該在run()中做一些初始化,然後調用exec()並將它傳遞給Qt。

如果你的線程除了檢查信號還需要運行一些週期性操作,你可以通過使用QTimer :: singleShot定時器將信號發送到同一個線程來實現。

http://qt-project.org/doc/qt-4.8/threads-qobject.html#signals-and-slots-across-threads

PS。如果您通過排隊連接傳遞指針,則指針必須有效,直到處理完信號,這可能是在發佈信號的函數存在之後。一個常見的錯誤是將帶有字符串的信號作爲參數存儲在本地char []緩衝區中。在訪問緩衝區的時候,原始函數完成了,字符串已經消失了。這些錯誤取決於線程調度,因此很難調試。如果你通過排隊連接傳遞指針,它們必須是堆分配的,被調用者必須負責釋放它們。

0

如果我正確理解你的問題,你有一個許多線程執行的回調函數。此回調函數應該發出一個信號連接到另一個線程中的對象的插槽。

我的建議是使用模式(moveToThread)創建一個線程接收器對象。然後將postEvent方法用於私有實現方法。該調用是線程安全的(參數被複制)。

所以你的回調可以直接和安全地調用:

OnProcessQueuedOutEvent 

該帖子將事件QThread的事件循環。

Receiver.h

class Receiver : public QObject 
{ 
    Q_OBJECT 
public: 
    explicit Receiver(QObject* parent = 0); 
    virtual ~Receiver(); 

public slots: 
    void OnProcessQueuedOutEvent(int val); 

private slots: 
    void OnProcessQueuedOutEventImpl(int val); 

private: 
    QThread m_thread; 
}; 

Receiver.cpp

Receiver::Receiver(QObject* parent) 
    : QObject(parent) 
{ 
    moveToThread(&m_thread); 
    m_thread.start(); 
} 

Receiver::~Receiver() 
{ 
    // Gracefull thread termination (queued in exec loop) 
    if(m_thread.isRunning()) { 
     m_thread.quit(); 
     m_thread.wait(); 
    } 
} 

void OnProcessQueuedOutEvent(int val) 
{ 
    QMetaObject::invokeMethod(this, "OnProcessQueuedOutEventImpl", Q_ARG(int,val)); 
} 

void OnProcessQueuedOutEventImpl(int val) 
{ 
    // do stuff here 
}