2011-05-19 664 views
4

我有一個RPC線程正在從該線程回調給我。我需要以某種方式通知Qt它需要從主線程進行函數調用。在直接的Windows中,我可以通過使用自定義消息來完成此操作,然後將該消息發佈到消息隊列中,例如,我可以創建WM_CALLFUNCTION消息並通過wParam和參數(類指針)通過lParam傳遞函數指針。使用Qt創建自定義消息/事件

有沒有人有一個想法,我怎麼可以用Qt做到這一點?我碰到過QCustomEvent,但我不知道如何使用它或如何處理它。任何幫助將非常感激!

編輯:

在我QMetaObject::invokeMethod去年底,其完美的作品。

+0

而不是QCustomeEvent,爲什麼不使用信號/插槽機制? – Arlen 2011-05-19 15:58:38

+0

以什麼方式......我將如何從線程B調用線程A以執行函數...? – Goz 2011-05-19 16:10:32

+1

Qt信號/插槽機制是線程安全的,可以跨線程使用。如果你不知道如何查找信號/插槽教程。 – Arlen 2011-05-19 16:23:32

回答

5

In Qt 3, the usual way to communicate with the GUI thread from a non-GUI thread was by posting a custom event to a QObject in the GUI thread. In Qt 4, this still works and can be generalized to the case where one thread needs to communicate with any other thread that has an event loop.

To ease programming, Qt 4 also allows you to establish signal--slot connections across threads. Behind the scenes, these connections are implemented using an event. If the signal has any parameters, these are also stored in the event. Like previously, if the sender and receiver live in the same thread, Qt makes a direct function call.

- 一般 http://doc.qt.nokia.com/qq/qq14-threading.html#signalslotconnectionsacrossthreads

+0

乾杯!但是,您究竟如何在線程間建立信號插槽連接? – Goz 2011-05-19 16:50:32

+0

對於一個...我是否需要從Qt線程運行來執行此操作?因爲我需要回調的線程是非QT線程... – Goz 2011-05-19 16:53:03

+0

GUI必須在主線程中運行。如果你沒有處理小部件,那麼你需要繼承QObject並實現你的信號/插槽。 – Arlen 2011-05-19 17:13:50

6

使用自定義事件涉及到創建自己的QEvent的子類中,將接收的事件(通常是主窗口類)和一些代碼QObject的類中重寫自定義事件()是將事件從您的線索「發佈」到接收器。

我喜歡將事件發佈代碼作爲接收者類的一種方法實現。這樣,調用者只需知道接收對象而不是任何「Qt」細節。調用者將調用這個方法,然後基本上將消息發送給自己。希望下面的代碼能夠使它更清晰。

// MainWindow.h 
... 
// Define your custom event identifier 
const QEvent::Type MY_CUSTOM_EVENT = static_cast<QEvent::Type>(QEvent::User + 1); 

// Define your custom event subclass 
class MyCustomEvent : public QEvent 
{ 
    public: 
     MyCustomEvent(const int customData1, const int customData2): 
      QEvent(MY_CUSTOM_EVENT), 
      m_customData1(customData1), 
      m_customData2(customData2) 
     { 
     } 

     int getCustomData1() const 
     { 
      return m_customData1; 
     } 

     int getCustomData2() const 
     { 
      return m_customData2; 
     } 

    private: 
     int m_customData1; 
     int m_customData2; 
}; 

public: 
void postMyCustomEvent(const int customData1, const int customData2); 
.... 
protected: 
void customEvent(QEvent *event); // This overrides QObject::customEvent() 
... 
private: 
void handleMyCustomEvent(const MyCustomEvent *event); 

customData1customData2在那裏演示如何可能會通過一些數據一起在你的事件。他們不必是int s。

// MainWindow.cpp 
... 
void MainWindow::postMyCustomEvent(const int customData1, const int customData2) 
{ 
    // This method (postMyCustomEvent) can be called from any thread 

    QApplication::postEvent(this, new MyCustomEvent(customData1, customData2)); 
} 

void MainWindow::customEvent(QEvent * event) 
{ 
    // When we get here, we've crossed the thread boundary and are now 
    // executing in the Qt object's thread 

    if(event->type() == MY_CUSTOM_EVENT) 
    { 
     handleMyCustomEvent(static_cast<MyCustomEvent *>(event)); 
    } 

    // use more else ifs to handle other custom events 
} 

void MainWindow::handleMyCustomEvent(const MyCustomEvent *event) 
{ 
    // Now you can safely do something with your Qt objects. 
    // Access your custom data using event->getCustomData1() etc. 
} 

我希望我沒有留下任何東西。有了這個地方,在一些其他線程的代碼只需要獲得一個指向MainWindow對象(姑且稱之爲mainWindow)和呼叫

mainWindow->postMyCustomEvent(1,2); 

那裏,只是我們的例子中,12可以是任意整數數據。

+0

'QApplication :: postEvent(this,new StatisticEvent(p,dltotal,dlnow,uptotal,upnow));'我得到錯誤,'/home/phobos/Programming/FyreDL/src/cmnroutines.cpp:1241: 29:錯誤:無法初始化類型爲'QObject *'的參數,類型爲'GekkoFyre :: StatisticEvent *'QApplication :: postEvent(this,new StatisticEvent(p,dltotal,dlnow,uptotal,upnow));''我不知道該怎麼做。有人可以幫忙嗎?這將不勝感激。 – 2016-10-22 22:57:00