Question

I have created a thread contains a QTcpServer which accepts any incoming connections:

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
    }
}

in handle(QTcpSocket *socket) :

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

Note: TimeDateSocketHandler is a subclass of SocketHandler and SocketHandler itself is a subclass of QThread as shown in the following:

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();
}

And finally here is the 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;
}

main function:

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();
}

In the main function I started the TimeDateService. But when I connect to the server for retrieving time and date, server sends time and date but when the TimeDateSocketHandler wants to close the socket the program crashes:

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

Can anyone help me out please how can I fix this problem, Many Thanks

Was it helpful?

Solution

Your problem is this line:

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

The parent "socket" lives in the TimeDateService thread, but the child will be in the TimeDateocketHandler thread. Parent and children should be in the same thread when using the Qt event loop.

Here is the relevant part of the 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:

The solution is relatively straight-forward:

  • You could call the method directly with the invokeMethod method of QMetaObject. You would need to use queued connection to get the slot triggered in the separate thread.

    QMetaObject::invokeMethod(new TimeDateSocketHandler(socket), SLOT(Start()), Qt::QueuedConnection);

or

  • Use signal and slots. This means emit a signal instead of direct invokation and then connect the other thread's corresponding slot.

    TimeDateSocketHandler *timeDateSocketHandler = new TimeDateSocketHandler(socket);

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

    emit socketHandled();

or

  • Use a smart pointer (like QSharedPointer) instead of raw pointer

  • Move to the socket handling into the other thread.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top