-3

I recently successfully implemented multithreading to my GUI application using method by reimplementing run() virtual void, but I read there is a lot of confusion around threading in QT as even documentation doesn't present it correctly. What I'm trying now is just to understand how it works and use it without any issues even not visible ones at first look. I'm wondering what can be wrong in my code below, as I'm getting info from Visual Studio when starting that some errors occured and I see "QtRunWork" task returned false but did not log an error." When I ignore this and start the program I'm getting in console this: "qt.core.qobject.connect: QObject::connect: No such slot QObject::process() in (..)main.cpp:38 qt.core.qobject.connect: QObject::connect: No such signal QObject::finished() in (..)main.cpp:39 qt.core.qobject.connect: QObject::connect: No such signal QObject::finished() in (..)main.cpp:40" "

#include <QtCore/QCoreApplication>
#include <QCoreApplication>
#include <QThread>
#include <QString>
#include <QDebug>

class Worker : public QObject {
 Q_OBJECT

public slots:
    
    void process() {

        qDebug() << "Thread1";
        emit finished();
    }

signals:
    void finished();
};

class MyThread : public QThread {

public:
    MyThread();

signals:
    void finished();
};

MyThread::MyThread() {

    Worker* w = new Worker();
    w->moveToThread(this);
    connect(this, SIGNAL(started()), w, SLOT(process()));
    connect(w, SIGNAL(finished()), this, SLOT(quit()));
    connect(w, SIGNAL(finished()), w, SLOT(deleteLater()));
    connect(this, SIGNAL(finished()), this, SLOT(deleteLater()));
    this->start();
}

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

    MyThread m;

    return a.exec();
}
Jacob
  • 57
  • 6
  • Apart from anything else `MyThread` needs the `Q_OBJECT` macro. – G.M. Jan 30 '22 at 18:46
  • True, now I'm getting "main.obj : error LNK2001: unresolved external symbol "public: virtual struct QMetaObject const * __cdecl Worker::metaObject(void)const " (?metaObject@Worker@@UEBAPEBUQMetaObject@@XZ) main.obj : error LNK2001: unresolved external symbol "public: virtual void * __cdecl Worker::qt_metacast(char const *)" (?qt_metacast@Worker@@UEAAPEAXPEBD@Z)" and x4 more.. – Jacob Jan 30 '22 at 19:03
  • 1
    Those errors are probably due to not compiling/linking with the updated code generated by `moc`. – G.M. Jan 30 '22 at 19:10
  • Nothing changed even when I created new project and copied the code. – Jacob Jan 30 '22 at 19:26
  • 1
    you need to include the moc file. See [this](https://stackoverflow.com/a/3005403/4179302). – apalomer Jan 30 '22 at 19:49
  • 1
    I'd stick to the standard and have a `*.h` and `*.cpp` file for each class. Then Qt better understands what is going on and assists with all the `moc` stuff. In my applications I almost never have to deal with problems related to `moc` files. – SebDieBln Jan 30 '22 at 19:54
  • I think I don't have to do this when using VisualStudio, only when working in QTCreator. Anyway I did as in this topic and it shouts with tons of errors from this file, e.g. error C2653: 'Worker': is not a class or namespace name, error C2065: 'Worker': undeclared identifier, error C2923: 'QtPrivate::TypeAndForceComplete': 'Worker' is not a valid template type argument for parameter 'T' – Jacob Jan 30 '22 at 20:02
  • @SebDieBln, Mate you saved me from brain melt, I don't get it why it's not working in single file, many thanks! – Jacob Jan 30 '22 at 20:33
  • 2
    Multithreading in Qt can get messed up if not implemented correctly. Recommended reading: [1](https://doc.qt.io/qt-5/threads-qobject.html), [2](https://wiki.qt.io/Threads_Events_QObjects), [3](https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/), [4](https://www.qt.io/blog/2010/06/17/youre-doing-it-wrong), [5](https://woboq.com/blog/qthread-you-were-not-doing-so-wrong.html), [6](https://www.kdab.com/the-eight-rules-of-multithreaded-qt/) – Arun Kumar B Jan 31 '22 at 07:50

1 Answers1

1

Do not declare signal finished in your thread class. QThread already has this signal https://doc.qt.io/qt-5/qthread.html#finished

  • I got it, I badly suggested article that @Arun Kumar B also [linked](https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/). There is `finished()` void added to QObject. Anyway, I wonder what if I'm using this method in GUI app as mentioned in my main post. In this case I'm not emiting `finished()` from the QObject but another one singal with string value to GUI. Would it be correct? `QObject::connect(worker, SIGNAL(emit_string(std::string)), worker, SIGNAL(finished())); QObject::connect(worker, SIGNAL(finished()), mThread, , SLOT(quit()));` – Jacob Jan 31 '22 at 22:18
  • Of course there is also signal->slot from emit_string to proper slot in GUI and further connections. – Jacob Jan 31 '22 at 22:40
  • Solved, I didn't know I can emit more than one signal, so from the worker I'm emitting first mine `emit_string(std::string)` and then `finished()`. No need to do above and I think it's bad as if I'm not wrong, it shouldn't be emitted signal with some value like string in this case to the slot that not takes this value. – Jacob Feb 01 '22 at 21:44