Qt send signal to different thread
Asked Answered
M

1

8

I have searched SO for this question, but they were a bit different than mine. My problem is that I don't want to receive a signal from another thread, but I want to send one. Receiving works in my app, but when trying to send, I am getting error that I am trying to send to another thread.

This is my situation:

I have a Gui application. In MainWindow class I create a myThread object, that is inherited from Qthread.

I then start the new thread. In MainWindow a signal exists and in myThread a slot exists (this code is run in main window). When I try to do:

connect(this, SIGNAL(disconnect(),
        connectionThread, SLOT(stop()));

stop() is a slot in connection thread and disconnect() is a signal from MainWindow. When the signal is emited, i get:

ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread 128f8250. Receiver '' (of type 'QNativeSocketEngine') was created in thread 14bae218", file kernel\qcoreapplication.cpp, line 521
Invalid parameter passed to C runtime function.
Invalid parameter passed to C runtime function.

Is there a way to overcome this? I need to be able to send and receive events through signals and slots to and from the thread I created.

PS: I tried directlinking.

connect(this, SIGNAL(disconnectFromOven()),
            connectionThread, SLOT(stop()), Qt::DirectConnection);

This is the code:

MainWindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>


namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    void moveUndoView();

signals:
    void disconnectFromOven();

};

#endif // MAINWINDOW_H

MainWindow.cpp:

#include "mainwindow.h"


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    initComponents();

    QString ip = "10.10.10.17";
    int port = 5432;
    connectionThread = new TcpThread(ip, port, connectAndStay);

    show();

    // tcp connection
    connect(connectionThread, SIGNAL(connectionEstablished()),
            this, SLOT(on_connectionEstablished()));

    connect(connectionThread, SIGNAL(connectionNotEstablished()),
                this, SLOT(on_connectionNotEstablished()));

    connect(this, SIGNAL(disconnectFromOven()),
            connectionThread, SLOT(stop()));


}


void MainWindow::on_action_Disconnect_triggered()
{
    emit disconnectFromOven();
}

tcpthread.h:

#ifndef TCPTHREAD_H
#define TCPTHREAD_H

#include <QThread>
#include <QDebug>

#include "tcpconnection.h"

class TcpThread : public QThread
{
    Q_OBJECT
public:
    explicit TcpThread(QString& address,
                       int& port, conType_t conType, QObject *parent = 0);
    void run(); // inherited


signals:
    void connectionStatusOk();
    void connectionEstablished();
    void connectionNotEstablished();

private slots:
    void stop();
    void connectionClosed();
    void connectionOpened();
    void connectionOpenFailed();

};

#endif // TCPTHREAD_H

tcpthread.cpp:

#include "tcpthread.h"

TcpThread::TcpThread(QString& address,
                     int& port, conType_t conType, QObject *parent) :
    QThread(parent)
{
    this->address = address;
    this->port = port;
    this->conTypeRequested = conType;
}

void TcpThread::stop()
{
    qDebug() << "Thread stop called, requesting disconnect";
    tcpCon->doDisconnect();
}
Mcdougal answered 28/4, 2015 at 14:12 Comment(10)
PS: I tried directlinking. <--- what do you mean with that?Hesky
Sorry, I means connecting: connect(this, SIGNAL(disconnectFromOven()), connectionThread, SLOT(stop()), Qt::DirectConnection);Barbie
And this is the problem. Just remove your Qt::DirectConnection. Problem solved.Hesky
This solved my problem when RECEIVING a signal from connectionThread. Vice versa doesnt work.Barbie
Of course it works. Or you have some other problem. Sending and receiving signal/slots between threads is probably one of the most used thread techniques in Qt.Hesky
Well I dont know what it could be. Only receiving works for me. I am getting the specified error when sending to the created thread. It says that I cannot send event to different thread.Barbie
Perhaps you show a bit more code?Hesky
there is a parenthesis missing from your first code sample. Typo?Koralle
Try to pass Qt::QueuedConnection explicitly, maybe the receiving object is still in the main thread at connection time so that AutoConnection type becomes DirectConnection, i'm not sure if explicit pass of QueuedConnection solves this problem. Anyway post more code.Seriatim
I have posted the code that consist this mechanism, I have cut some of it that is unrevelant and shading. I have tried Qt::QueuedConnection as well, doesnt work.Barbie
S
-1

QThread (connectionThread) instance lives in the thread that instantiated it (main thread), not in the thread that calls run(), so if you want to call slots you need to use the first approach presented in the documentation here, look at the worker-object approach.

Seriatim answered 28/4, 2015 at 14:43 Comment(9)
And I propose additionally this documentation: woboq.com/blog/qthread-you-were-not-doing-so-wrong.htmlHesky
Hi, I have added this->moveToThread(connectionThread); after the pointer allocation, but this also did not solve my problem :/. Did I do it correctly?Barbie
Isn't this in that context the main window? You don't need to move the main window to the thread, try this: connectionThread->moveToThread(connectionThread); Or much better use the worker object method presented in the documentation.Seriatim
And don't forget to connect the finished() signal to deleteLater() slot for connectionThread so that you won't leak that memory.Seriatim
@ŁukaszPrzeniosło I thinks the point here is that if you are going to use a slot in your QThread, you shouldn't be subclassing QThread. You can just create and object and pass it to a QThread as the first example in the link posted by ZlatomirHypothermal
Thank you, after doing connectionThread->moveToThread(connectionThread); it is working now. It would be some coding for me now now to subclass Qthread, but why is that bad? I am not using Qt for a long time, but every site i go, they have a different opinion about subclassing it.Barbie
@ŁukaszPrzeniosło This is a popular post about that subject and the link posted by Greenflow is a follow-up to it. They talk about the different approaches to the use of QThread.Hypothermal
@ŁukaszPrzeniosło Don't do things like this->moveToThread(this); or connectionThread->moveToThread(connectionThread);. It's a hack that shouldn't be used. Use the worker object design. You should also read this article.Vernal
I downvoted this post because it vaguely defers explanation to documentation, without even specifically saying which part.Terramycin

© 2022 - 2024 — McMap. All rights reserved.