8

I have searched SO for this question, but they were a bit different than mine. My problem is that I dont 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... I dont know how to fix this. 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. I Would really aprichiate all help!

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();
}
Łukasz Przeniosło
  • 2,725
  • 5
  • 38
  • 74
  • 2
    PS: I tried directlinking. <--- what do you mean with that? – Greenflow Apr 28 '15 at 14:15
  • Sorry, I means connecting: connect(this, SIGNAL(disconnectFromOven()), connectionThread, SLOT(stop()), Qt::DirectConnection); – Łukasz Przeniosło Apr 28 '15 at 14:15
  • 2
    And this is the problem. Just remove your Qt::DirectConnection. Problem solved. – Greenflow Apr 28 '15 at 14:16
  • This solved my problem when RECEIVING a signal from connectionThread. Vice versa doesnt work. – Łukasz Przeniosło Apr 28 '15 at 14:17
  • 1
    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. – Greenflow Apr 28 '15 at 14:19
  • 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. – Łukasz Przeniosło Apr 28 '15 at 14:22
  • Perhaps you show a bit more code? – Greenflow Apr 28 '15 at 14:25
  • there is a parenthesis missing from your first code sample. Typo? – ratchet freak Apr 28 '15 at 14:25
  • 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. – Zlatomir Apr 28 '15 at 14:27
  • 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. – Łukasz Przeniosło Apr 28 '15 at 14:32

1 Answers1

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

Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778
Zlatomir
  • 6,964
  • 3
  • 26
  • 32
  • 1
    And I propose additionally this documentation: http://woboq.com/blog/qthread-you-were-not-doing-so-wrong.html – Greenflow Apr 28 '15 at 15:08
  • Hi, I have added this->moveToThread(connectionThread); after the pointer allocation, but this also did not solve my problem :/. Did I do it correctly? – Łukasz Przeniosło Apr 28 '15 at 15:15
  • 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. – Zlatomir Apr 28 '15 at 15:19
  • And don't forget to connect the _finished()_ signal to _deleteLater()_ slot for _connectionThread_ so that you won't leak that memory. – Zlatomir Apr 28 '15 at 15:22
  • @Ł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 Zlatomir – Maxito Apr 28 '15 at 15:22
  • 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. – Łukasz Przeniosło Apr 28 '15 at 15:31
  • @ŁukaszPrzeniosło [This](http://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/) 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. – Maxito Apr 28 '15 at 15:36
  • @Ł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](http://wiki.qt.io/Threads_Events_QObjects#Signals_and_slots_across_threads). – thuga Apr 29 '15 at 06:55
  • 3
    I downvoted this post because it vaguely defers explanation to documentation, without even specifically saying which part. – Tomáš Zato Aug 02 '16 at 22:40