2013-10-15 25 views
0

我試圖用我已經在一個單獨的QThread使用qUdpSocket寫了一個udpReceiver類接收一些接收的數據包:UDP包不QThread的

class udpThread : public QThread 
{ 
private: 
    QObject * parent; 
public: 
    udpThread(QObject * parent = 0) 
    { 
     this->parent = parent; 
    } 

    void run() 
    { 
     UdpReceiver * test = new UdpReceiver(parent); 
    } 
}; 


class UdpReceiver : public QObject 
{ 
    Q_OBJECT 
private: 
    QUdpSocket * S; 
    int port; 
public: 
    UdpReceiver(QObject* parent = 0) : QObject(parent) 
    { 
     port = 9003; 
     initialize(); 
    } 
    UdpReceiver(int p,QObject* parent = 0) : QObject(parent) 
    { 
     port = p; 
     initialize(); 
    } 

    void initialize() 
    { 
     S = new QUdpSocket(); 
     S->bind(port); 
     S->connect(S,SIGNAL(readyRead()),this,SLOT(readPendingDiagrams())); 
     qDebug() << "Waiting for UDP data from port " << port << " ... \n"; 
    } 

public slots: 
    void readPendingDiagrams() 
    { 
     while(S->waitForReadyRead()) 
     { 
      QByteArray datagram; 
      datagram.resize(S->pendingDatagramSize()); 
      QHostAddress sender; 
      quint16 senderPort; 

      S->readDatagram(datagram.data(), datagram.size(),&sender, &senderPort); 
      qDebug() << datagram.size() << " bytes received .... \n"; 
      qDebug() << " bytes received .... \n"; 
     } 
    } 
}; 

這裏是main()方法:

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 



// UdpReceiver * net = new UdpReceiver();  

    MainWindow w; 

    udpThread * ut = new udpThread(); 
    ut->start(); 

    w.show(); 


    return a.exec(); 
} 

現在,當我使用udpReceiver類來獲取數據包,而不只是正常的QThread,但是當我使用udpThread類它不會報文,或在至少raedyread()信號不會激活某些方式。 當我嘗試獲取沒有QThread的數據包時,我的GUI以某種方式崩潰,整個程序掛起,這就是爲什麼我想使用QThread。 我很欣賞你能不能幫我解決這個:) 問候,

+0

你在'run()'函數中遺漏了一些代碼嗎?你所要做的就是創建你的'UdpReceiver',然後退出正在運行的線程。 – RobbieE

回答

1

你陷入同樣的​​陷阱許多Qt中使用線程工作時做到:http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/。它幾乎是子類QThread總是一個壞主意(見http://woboq.com/blog/qthread-you-were-not-doing-so-wrong.html爲反例)。

按如下方式更改您的代碼以執行「預期」方式(創建一個新的QThread並在您的QObject上調用moveToThread以將其移至新線程)。你會從輸出的UdpReceiver是在創建線程是不一樣的一個接收到的數據,看看哪個是你想要什麼:

#include <QApplication> 
#include <QDebug> 
#include <QThread> 
#include <QUdpSocket> 

class UdpReceiver : public QObject 
{ 
    Q_OBJECT 
private: 
    QUdpSocket * S; 
    int port; 
public: 
    UdpReceiver(QObject* parent = 0) : QObject(parent) 
    { 
     qDebug() << "Construction thread:" << QThread::currentThreadId(); 

     port = 9003; 
     initialize(); 
    } 
    UdpReceiver(int p,QObject* parent = 0) : QObject(parent) 
    { 
     port = p; 
     initialize(); 
    } 

    void initialize() 
    { 
     S = new QUdpSocket(); 
     S->bind(port); 
     S->connect(S,SIGNAL(readyRead()),this,SLOT(readPendingDiagrams())); 
     qDebug() << "Waiting for UDP data from port " << port << " ... \n"; 
    } 

public slots: 
    void readPendingDiagrams() 
    { 
     qDebug() << "Reading thread:" << QThread::currentThreadId(); 

     while(S->waitForReadyRead()) 
     { 
      QByteArray datagram; 
      datagram.resize(S->pendingDatagramSize()); 
      QHostAddress sender; 
      quint16 senderPort; 

      S->readDatagram(datagram.data(), datagram.size(),&sender, &senderPort); 
      qDebug() << datagram.size() << " bytes received .... \n"; 
      qDebug() << " bytes received .... \n"; 
     } 
    } 
}; 

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 

    QThread *t = new QThread(); 
    t->start(); 

    UdpReceiver * net = new UdpReceiver(); 
    net->moveToThread(t); 

    return a.exec(); 
} 

#include "main.moc" 

我沒有你的UI代碼,所以我不知道那裏有任何問題。如果您遇到困難,請隨時發佈另一個問題,並在評論中提及它,我會盡力提供幫助。

+0

非常感謝,謝謝! 但是當我用你的建議我在控制檯幾次得到這個消息: 「在QSocketNotifier:插座通知者不能從另一個線程關閉」 它說的是,我應該(從另一個線程禁用套接字)擔心?我怎樣才能解決這個問題? –

+0

對不起,我從來沒有真正看到該消息。也許你應該發佈一個新問題。如果我有一段時間後我可以看看。 – ksimons

0

瓦希德Nateghi,初始化代碼和工作代碼必須在同一個線程中運行。但是UdpReceiver的構造函數在主線程中運行,這是readPendingDiagrams運行時的一個缺陷。試試這個:

#include <QCoreApplication> 
#include <QDebug> 
#include <QThread> 
#include <QUdpSocket> 

class UdpReceiver : public QObject 
{ 
    Q_OBJECT 
private: 
    QUdpSocket * S; 
    int port; 
public: 
    UdpReceiver(QObject* parent = 0) : QObject(parent) 
    { 
     qDebug() << ">HERE was the bug! thread:" << QThread::currentThreadId() << "in Construction of UdpReceiver:" << __LINE__ ; 
    } 

public slots: 
    void init_thread(){ 
     port = 10000; 
     qDebug() << ">thread:" << QThread::currentThreadId() << "in init_thread:" << __LINE__ ; 
     S = new QUdpSocket(); 
     S->bind(port); 
     S->connect(S,SIGNAL(readyRead()),this,SLOT(readPendingDiagrams())); 
     qDebug() << "Waiting for UDP data from port " << port << " ... \n"; 
    } 
    void readPendingDiagrams() 
    { 
     qDebug() << ">thread:" << QThread::currentThreadId() << "in readPendingDiagrams:" << __LINE__ ; 


     while(S->waitForReadyRead()) 
     { 
      QByteArray datagram; 
      datagram.resize(S->pendingDatagramSize()); 
      QHostAddress sender; 
      quint16 senderPort; 

      S->readDatagram(datagram.data(), datagram.size(),&sender, &senderPort); 
      qDebug() << datagram.size() << " bytes received in thread " << QThread::currentThreadId() << "in readPendingDiagrams:" << __LINE__ ; 
     } 
    } 
}; 

int main(int argc, char *argv[]) 
{ 
    qDebug() << ">Main thread:" << QThread::currentThreadId() << "in main:" << __LINE__ ; 
    QCoreApplication a(argc, argv); 

    QThread *t = new QThread(); 


    UdpReceiver * net = new UdpReceiver(); 
    net->moveToThread(t); 
    net->connect(t,SIGNAL(started()),net,SLOT(init_thread())); 
    t->start(); 

    return a.exec(); 
} 

#include "main.moc"