4

I am new to QT. I need to use threads for some purpose. I searched a lot about threading in QT but all the articles and videos are using same example. They are using dialog and putting a label with 2 buttons to print some data on label. I want to use threads with MainWindow. My application include reading a serial data and then displaying the related information on a label. That information contains a string and an audio file. String and audio file needs to be played at the same time. I have a connected a signal for serial read like below:

connect(&Serial, SIGNAL(readyRead()), this, SLOT(SerialRead()));

QString MainWindow::SerialRead()
{
  word Words; //
  QString serialData = Serial.readAll();              //Reading Serial Data
  //Now here I want to start the two threads
  //Thread 1 to display string
  //Thread 2 to play audio
  return 0;

}

How can I achieve above task. Can anyone please refer me to some usefull links or articles. Thanks

S Andrew
  • 5,592
  • 27
  • 115
  • 237
  • You need another object that lives in the worker thread (c.f. `moveToThread()`). You can't use the slot in `MainWindow`. – Karsten Koop Apr 03 '17 at 06:55
  • 1
    I suggest following the pattern that is described in [this excellent article](https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/) – TheDarkKnight Apr 03 '17 at 12:17

2 Answers2

4

While I very highly recommend that you use std::thread instead of QThread, it's your call. However, on the Qt docs page of QThread there's a very good example that exactly fits what you need. Here it's:

class Worker : public QObject
{
    Q_OBJECT

public slots:
    void doWork(const QString &parameter) {
        QString result;
        /* ... here is the expensive or blocking operation ... */
        emit resultReady(result);
    }

signals:
    void resultReady(const QString &result);
};

class Controller : public QObject
{
    Q_OBJECT
    QThread workerThread;
public:
    Controller() {
        Worker *worker = new Worker;
        worker->moveToThread(&workerThread);
        connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
        connect(this, &Controller::operate, worker, &Worker::doWork);
        connect(worker, &Worker::resultReady, this, &Controller::handleResults);
        workerThread.start();
    }
    ~Controller() {
        workerThread.quit();
        workerThread.wait();
    }
public slots:
    void handleResults(const QString &);
signals:
    void operate(const QString &);
};

Basically, in this example, the Controller is your MainWindow, and the constructor of Controller is your MainWindow::SerialRead(). Be careful with memory and thread management though if you want to do that, because that Controller is made to destroy things when it exists, not when the thread is finished.

So you either use that controller as is (simply instantiate it in your MainWindow::SerialRead()), or change it to include parts of it in your MainWindow.

The Quantum Physicist
  • 24,987
  • 19
  • 103
  • 189
  • Thanks for this example. BTW by `std::thread` did you mean using pthreads. Does pthread works great for qt creator. Or did you mean anything else.? – S Andrew Apr 03 '17 at 07:13
  • @SAndrew `std::thread` is C++11. It's the new standard of C++ that has a thread implementation by itself. It's very low level and you have lots of freedom. You have to spend a few days learning how to use it before saying hello in a serious program, but once you learn it, you'll love it. I stopped using QThread for a while now after C++11 came out. – The Quantum Physicist Apr 03 '17 at 07:16
  • Please give me a link – S Andrew Apr 03 '17 at 07:19
  • 1
    @SAndrew Here's a link to a reference: http://en.cppreference.com/w/cpp/thread/thread ; and here's a link to a very good book: https://www.amazon.com/C-Concurrency-Action-Practical-Multithreading/dp/1933988770 – The Quantum Physicist Apr 03 '17 at 07:19
  • *I very highly recommend that you use std::thread instead of QThread* - Please explain why you recommend this. The benefit of QThread is its integration with Qt's signals and slots. – TheDarkKnight Apr 03 '17 at 12:20
  • @TheDarkKnight It boils down eventually to using less Qt resources + taste. I have a rule: If you musn't use externals, then don't use them. I mean, what's the benefit of using `QThread` of `std::thread`? Nothing! On the other hand, using `std::thread` is better because it's part of the standard and makes your classes reusable. Also about signals and slots, it's not that good. It's great for GUIs, but for multithreading? Really? In my opinion it's a very expensive solution to a very simple problem. This is a big discussion that we can't finish here. It's all experience and opinion though. – The Quantum Physicist Apr 03 '17 at 12:27
  • 1
    @TheQuantumPhysicist, *Also about signals and slots, it's not that good* - this is where we disagree; signals and slots promotes loose coupling and makes multi-threading easy (no mutexes!). Without signals and slots of Qt, I'd be writing my own. QThread isn't a thread, but more like a thread controller. Thanks for explaining your viewpoint. – TheDarkKnight Apr 04 '17 at 08:07
  • @TheDarkKnight To me, signals and slots + QThread is just a function queue... with C++11 you can easily make a thread-safe function queue using `std::bind` and `std::function` (and without mutexes, too, using `std::atomic`). Worst case, one could use `boost::ASIO::io_service`, which is light-weight compared to QThread. My only problem with QThread is that it's really, really gigantic and expensive (leave alone that it fucks up licensing with LGPL if you're not rich). But it's all opinion, like I said in the beginning. You can make perfect programs with both options :) Cheers! – The Quantum Physicist Apr 04 '17 at 08:13
  • 1
    I agree, it's all opinion and I'm interested in yours (and others), even if I may disagree. The other reason I prefer QThread is that its design naturally leads to encapsulation of data for jobs, as described in the answer to [this question](http://stackoverflow.com/questions/40284850/qthread-vs-stdthread) – TheDarkKnight Apr 04 '17 at 08:18
-2

you may not need to use 2 threads to do such things. just emit a signal connected to setText(const QString&) and the other signal connected to the slot for playing audio. what is the size of serial data?

GestureWei
  • 27
  • 2
  • serial data will be integer like 1 or 2. Based on this I have to fetch string from a file and play corresponding audio. Can you show me an example – S Andrew Apr 03 '17 at 07:17
  • @SAndrew In this case, you can just do such two things in `MainWindow::SerialRead` if the file is small and the audio is short. You can also read the file in another thread but you have to show it in the main thread. How frequently does your serial data trigger? – GestureWei Apr 03 '17 at 08:46