c++ - 从另一个线程(子线程)访问QTcpSocket

标签 c++ qt qthread qtcore qtnetwork

我创建了一个包含QTcpServer 的线程,它接受任何传入的连接:

void Service::run() //Service class is a subclass of QThread
{
    server->listen(QHostAddress::LocalHost, ServicePortNo);
    // server is a private member of Service    

    while(server->waitForNewConnection(-1)){
        QTcpSocket *socket = server->nextPendingConnection();
        handle(socket); // This is a pure virtual function
    }
}

handle(QTcpSocket *socket) 中:

// TimeDateService is subclass of Service
// implementation of pure virtual function handle()
void TimeDateService::handle(QTcpSocket *socket)
{
    (new TimeDateSocketHandler(socket))->Start();
}

注意:TimeDateSocketHandlerSocketHandler的子类,SocketHandler本身是QThread的子类如下图:

void SocketHandler::run()
{
    if(!socket->waitForReadyRead(WAIT_TIMEOUT))
    {
        socket->disconnectFromHost();
        socket->close();
        return;
    }
    QByteArray request = socket->readAll();
    QByteArray response = Serve(request); // Serve is a pure virtual function
    socket->write(response);
    socket->waitForBytesWritten(WAIT_TIMEOUT);
    socket->disconnectFromHost();
    socket->close();
}

最后是 TimeDateSocketHandler

QByteArray TimeDateSocketHandler::Serve(QByteArray request)
{
    QByteArray response;
    response.append(QTime::currentTime().toString().toUtf8());
    response.append(QString(SEPARATOR).toUtf8());
    response.append(QDate::currentDate().toString().toUtf8());
    return response;
}

主要功能:

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

    TimeDateService timedateService;
    //CalculatorService calculatorService;
    //RemoteCMDService remoteCMDService;

    timedateService.StartService();
    //calculatorService.StartService();
    //remoteCMDService.StartService();

    return a.exec();
}

main 函数中,我启动了 TimeDateService。但是,当我连接到服务器以检索时间和日期时,服务器会发送时间和日期,但是当 TimeDateSocketHandler 想要关闭套接字时,程序崩溃了:

ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects ow ned by a different thread. Current thread 3998779bf0. Receiver '' (of type 'QNat iveSocketEngine') was created in thread 39985efcd0", file kernel\qcoreapplicatio n.cpp, line 494

谁能帮我解决这个问题,非常感谢

最佳答案

你的问题是这一行:

(new TimeDateSocketHandler(socket))->Start();

父“套接字”位于 TimeDateService 线程中,但子“套接字”位于 TimeDateocketHandler 线程中。使用 Qt 事件循环时父子应该在同一个线程中。

这里是 documentation 的相关部分:

Event filters are supported in all threads, with the restriction that the monitoring object must live in the same thread as the monitored object. Similarly, QCoreApplication::sendEvent() (unlike postEvent()) can only be used to dispatch events to objects living in the thread from which the function is called. Here is an example of that:

解决方案相对简单:

  • 您可以直接使用 invokeMethod method of QMetaObject 调用该方法.您需要使用排队连接来在单独的线程中触发插槽。

    QMetaObject::invokeMethod(new TimeDateSocketHandler(socket), 插槽(开始()), Qt::QueuedConnection);

  • 使用信号和槽。这意味着发出一个信号而不是直接调用,然后连接另一个线程的相应插槽。

    TimeDateSocketHandler *timeDateSocketHandler = new TimeDateSocketHandler(socket);

    connect(this, SIGNAL(socketHandled()), timeDateSocketHandler, SLOT(Start()));

    发出 socketHandled();

  • 使用智能指针(如 QSharedPointer)代替原始指针

  • 将套接字处理移至另一个线程。

关于c++ - 从另一个线程(子线程)访问QTcpSocket,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21086256/

相关文章:

c++ - 在 64 位 SQL Server 2008 R2 上运行 32 位扩展存储过程

java - ArrayDeque 类的字符

python - 如何在pyqt pyside中同时运行对象的多个实例

c++ - QThread 永远不会启动

c++ - 限制 boost make_shared 采用的参数

c++ - Windows Media Foundation - 使用模拟相机/采集卡

c++ - Qt 使用其他项目作为依赖

qt - SailfishOS/Qt - 如何在给定日期调用我的应用程序,比如几周后

c++ - QObject 的多重继承

c++ - 我什么时候应该使用 QThread::HighestPriority