2014-03-27 57 views
2

我正在嘗試開發一個簡單的Qt應用程序。 按下「START」按鈕後,應用程序應連續從設備中檢索數據(使用第三方庫),並在串行連接上儘快轉發它們。Qt - 獲取數據並通過串行連接轉發它們

我以前到現在是在一個連續的方式運行,並因爲它們是由主機提供儘快得到數據幀中的控制檯應用程序,使用以下週期的(醜陋的)軟件:

while(1) 
    { 
      [...] 
     while(MyClient.GetFrame().Result != Result::Success) 
     { 
      Sleep(200); 
      std::cout << "."; 
     } 

      [... pack and send on serial] 
    } 

我想知道在Qt中實現這個更方便的方法是什麼,以便保持GUI響應,而且getFrame和串行寫入函數之間的延遲最小。

我應該用定時器觸發SLOTQt併發命名空間QRunnable? 這些方法的主要優點和缺點是哪些?

謝謝 爲您的幫助!

回答

1

由於現有庫迫使您輪詢數據,唯一要做的就是在計時器上運行它。如果執行此作業的對象將在主線程或工作線程中運行,那麼這是您的選擇。沒有必要使用Qt Concurrent和QRunnable - 使用QObject使生活變得更簡單,因爲您可以輕鬆地向GUI提供反饋。

例如,使你的客戶的API一些假設:

class Worker : public QObject { 
    Client m_client; 
    QSerialPort m_port; 
    QBasicTimer m_timer; 

    void processFrame() { 
    if (m_client.GetFrame().Result != Result::Success) return; 
    QByteArray frame = QByteArray::fromRawData(
     m_client.GetFrame().Data, m_client.GetFrame().Size); 
    ... process the frame 
    if (m_port.write(frame) != frame.size()) { 
     ... process the error 
    } 
    } 
    void timerEvent(QTimerEvent * ev) { 
    if (ev->timerId() == m_timer.timerId()) processFrame(); 
    } 
public: 
    Worker(QObject * parent = 0) : QObject(parent) {} 
    Q_SLOT bool open(const QString & name) { 
    m_port.close(); 
    m_port.setPortName(name); 
    if (!m_port.open(name)) return false; 
    if (!m_port.setBaudRate(9600)) return false; 
    if (!m_port.setDataBits(QSerialPort::Data8)) return false; 
    ... other settings go here 
    return true; 
    } 
    Q_SLOT void start() { m_timer.start(200, this); } 
    Q_SLOT void stop() { m_timer.stop(); } 
    ... 
} 

/// A thread that's always safe to destruct 
class Thread : public QThread { 
    using QThread::run; // lock the default implementation 
public: 
    Thread(QObject * parent = 0) : QThread(parent) {} 
    ~Thread() { quit(); wait(); } 
}; 

int main(int argc, char ** argv) { 
    QApplication app(argc, argv); 
    Worker worker; 
    Thread thread; // worker must be declared before thread! 
    if (true) { 
    // this code is optional, disabling it should not change things 
    // too much unless the client implementation blocks too much 
    thread.start(); 
    worker.moveToThread(&thread); 
    } 

    QPushButton button("Start"); 
    QObject::connect(&button, &QPushButton::clicked, [&worker]{ 
    // Those are cross-thread calls, they can't be done directly 
    QMetaObject::invoke(&worker, "open", Q_ARG(QString, "COM1"); 
    QMetaObject::invoke(&worker, "start"); 
    }); 
    button.show(); 

    return app.exec(argc, argv); 
} 
相關問題