ทำไม QTcpSocket จึงไม่ส่งสัญญาณ?

ฉันมีปัญหากับ QTcpSocket มันไม่ส่งสัญญาณใดๆ :/


void NetworkInstance::run()
{
    m_pSocket = new QTcpSocket();
    connect(m_pSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError()));
    connect(m_pSocket, SIGNAL(hostFound()), this, SLOT(socketHostLookupDone()));
    connect(m_pSocket, SIGNAL(connected()), this, SLOT(socketConnected()));
    connect(m_pSocket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));

    connect(m_pSocket, SIGNAL(readyRead()), this, SLOT(socketReadyRead()));

    QSettings s;
    s.beginGroup("network");
    emit log(QString("Connection to: ").append(s.value("host").toString()).append(":").append(s.value("port").toString()));
    m_pSocket->connectToHost(s.value("host").toString(), s.value("port").toInt());
    s.endGroup();

    exec();
}

นี่คือรหัสของฉัน ฉันไม่เห็นข้อผิดพลาดใดๆ แต่ไม่มีสัญญาณที่เชื่อมต่ออยู่เลย (hostFound, เชื่อมต่อแล้ว ฯลฯ) บนเซิร์ฟเวอร์ ฉันเห็นว่าการเชื่อมต่อถูกสร้างขึ้นและส่งข้อมูลไปแล้ว แต่ไม่มีอะไรเกิดขึ้นที่ฝั่งไคลเอ็นต์ NetworkInstance กำลังขยาย QThread


person graywolf    schedule 13.08.2013    source แหล่งที่มา
comment
หากคุณกำลังจัดคลาสย่อย QThread คุณกำลังทำผิด: blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong   -  person TheDarkKnight    schedule 13.08.2013
comment
คุณไม่จำเป็นต้องใช้ QThread เลย! คุณสามารถรันสิ่งนี้ได้อย่างปลอดภัยในเธรดหลัก หลังจากที่ QTcpSocket ทั้งหมดทำงานแบบอะซิงโครนัส   -  person Marek R    schedule 14.08.2013
comment
ฉันต้องการ QThread ฉันทำการประมวลผลอย่างหนักกับข้อมูลที่ได้รับ (และใช่ มันเป็นไปได้ที่จะนำการประมวลผลไปไว้ใน QThread ด้วยตัวเอง แต่วิธีนี้ง่ายกว่า) ฉันมีปลั๊กหนึ่งตัวต่อหนึ่งเธรด ซึ่งตรงกับความต้องการของฉัน อย่างไรก็ตามคำตอบที่ยอมรับได้คือวิธีแก้ปัญหา   -  person graywolf    schedule 14.08.2013


คำตอบ (2)


จากความคิดเห็นก่อนหน้านี้ของฉันว่าคลาสย่อย QThread ผิด สิ่งที่คุณต้องทำคือสร้างคลาสของคุณที่สืบทอดมาจาก QObject จากนั้นย้ายสิ่งนั้นไปยัง QThread ใหม่

ดังนั้นคุณจะมีชั้นเรียนที่มีลักษณะดังนี้: -

class NetworkInstance : public QObject
{
    Q_OBJECT

public:
    NetworkInstance();

public slots:
    void Run();

    void socketConnected();
    void socketError();
    // etc for other slots...

private:
    class QTCPSocket* m_pSocket;
}

สร้างออบเจ็กต์อินสแตนซ์เครือข่ายและเธรดของคุณ: -

QThread* pThread = new QThread;
NetworkInstance* pNetworkInstance = new NetworkInstance;

สร้างอินสแตนซ์ QTCPSocket และเชื่อมต่อสัญญาณ / สล็อตในคลาส NetworkInstance ของคุณ จากนั้นสร้าง QThread และย้ายคลาสของคุณไปที่เธรด: -

pNetworkInstance->moveToThread(pThread);

สุดท้ายให้เริ่มการทำงานของเธรด: -

pThread->start();
person TheDarkKnight    schedule 13.08.2013
comment
วิธีที่ซับซ้อนน้อยกว่าในการบรรลุจุดสิ้นสุดเดียวกันคือซับคลาส QObject และ QRunnable จากนั้นส่งผู้ปฏิบัติงานไปที่ QThreadPool - person RobbieE; 13.08.2013
comment
ไม่แน่นอน IMHO 'ซับซ้อนน้อยกว่า' แต่ฉันยอมรับว่ามันเป็นอีกวิธีที่เป็นไปได้ - person TheDarkKnight; 13.08.2013
comment
ที่จริงแล้วเขาไม่ต้องการ QThread เลย QTCPSocket ทำงานแบบอะซิงโครนัส - person Marek R; 14.08.2013
comment
จริงอยู่ แต่บางทีคลาสของเขาอาจประมวลผลแพ็กเก็ตขาเข้าและต้องการทำสิ่งนั้นในเธรดอื่น - person TheDarkKnight; 14.08.2013

ฉันแน่ใจว่าสัญญาณถูกปล่อยออกมา ฉันไม่แน่ใจว่าจะได้รับจากช่องในเธรดอื่น ควรจะเป็น. โดยทั่วไป.

Qt::การเชื่อมต่ออัตโนมัติ

(ค่าเริ่มต้น) หากสัญญาณถูกปล่อยออกมาจากเธรดที่แตกต่างจากออบเจ็กต์ที่รับสัญญาณ สัญญาณจะถูกจัดคิว ซึ่งทำงานเป็น Qt::QueuedConnection มิฉะนั้น สล็อตจะถูกเรียกใช้โดยตรง โดยทำงานเป็น Qt::DirectConnection ประเภทของการเชื่อมต่อจะถูกกำหนดเมื่อมีการส่งสัญญาณ

แต่ตอนนี้คุณเริ่ม eventloop ของคุณเองด้วย exec() ใน run()

แก้ไข: อ่า... เข้าใจแล้ว...

Qt::การเชื่อมต่อที่อยู่ในคิว

สล็อตถูกเรียกใช้เมื่อการควบคุมกลับสู่ลูปเหตุการณ์ของเธรดของผู้รับ สล็อตถูกดำเนินการในเธรดของผู้รับ

นั่นคือสิ่งที่ถูกใช้โดยอัตโนมัติเนื่องจากผู้ส่งและผู้รับอยู่ในเธรดที่ต่างกัน แต่ด้วย 'exec()' ของคุณ การควบคุมจะไม่กลับไปที่เธรดของผู้รับ

person Greenflow    schedule 13.08.2013
comment
ดังนั้น .. คุณบอกว่าฉันไม่ควรเริ่ม eventloop ของตัวเองด้วย exec()? ฉันไม่แน่ใจว่ามันจะทำงานอย่างไรถ้าไม่มีมัน แต่ลองแล้วไม่ได้ช่วยอะไร - person graywolf; 13.08.2013