如何使用多线程创建一个简单的Qt控制台应用程序? [英] Howto make a simple Qt console application with multithreading?

查看:1142
本文介绍了如何使用多线程创建一个简单的Qt控制台应用程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个非常困难的时候了解如何使一个最简单可能的工作
多线程Qt 控制台应用程序。

I have a very difficult time of understanding how to make a simplest possible working multithreaded Qt console application.

我已经读了很多关于如何使用QThread类的东西。
其中一些说子类QThread,其他人说对QThread使用工人类包装。

I have read tons of stuff on how to use QThread class. Some of them say subclass QThread, others say use worker class wrapper for QThread.

经过几次尝试和重试后,我仍然不能做一个工作的多线程
Qt控制台应用程序。

After several tries and retries I could still not make a working multithreaded Qt console application.

现在我不需要任何奇特的Qt Gui。

Right now I don't need any fancy Qt Gui.

有人可以帮我填线程部分的示例代码?
它只是从文本文件中读取一行,并且想法是每个线程(我想使用4线程),现在不忙,将打印该行stdout与std :: cout尽快尽可能。只是打印它,现在没有其他奇怪的处理的东西,为我保持这个简单。

Can someone please help me to fill the threading parts of the example code ? It just reads one line at the time from text file and the idea is that each thread (I want to use 4 threads) that is not busy at the moment will print that line to stdout with std::cout as soon as possible. Just print it, no other fancy processing stuff for now to keep this simple for me.

#include <QCoreApplication>
#include <QFile>
#include <iostream>

/* QThread stuff here */
/* Don't know how to make it */

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

        /* Create four instances of threads here and 
           put them to wait readed lines */

    QFile   file("file.txt");
    file.open(QIODevice::ReadOnly | QIODevice::Text);

    while(!file.atEnd()) {
    /* Read lines here but where should they be saved?
       Into a global variable like QList<QByteArray> list ?
       So that each thread can read them from there or where ???? */

       ??? = file.readLine(); 
    }
    file.close();
    a.exit();
}


推荐答案

将功能放入插槽在QObject中



关键点是:

Putting the Functionality in a Slot in a QObject

The key points are:


  1. 每个 QObject 有一个特定的 thread()它生存。每个线程可以有一个事件循环。

  1. Remember that each QObject has a certain thread() that it "lives" in. Each thread can have an event loop running there. This event loop will deliver the events sent to the objects that "live" in this thread.

不要从中导出QThread

Do not derive from QThread. Start stock QThreads. They'll start an even event loop in the default implementation of QThread::run().

在插槽(或 Q_INVOKABLE )方法中实现您的功能。该类显然必须从 QObject 派生。

Implement your functionality in a slot (or a Q_INVOKABLE) method. The class obviously has to derive from QObject.

- 时隙连接,而不是直接)到#3中的插槽。从GUI线程中运行的通知程序到通知对象的连接使用 Qt :: QueuedConnection 自动完成,因为发送者和接收者对象存在于不同的线程中。

The magic happens when you send signals (using signal-slot connection, not directly) to the slot in #3. The connection from the notifier, running in the GUI thread, to the notified objects is done automatically using the Qt::QueuedConnection since the sender and the receiver objects live in different threads.

向这样的对象发送信号导致将事件发布到对象所在的线程的事件队列中。事件循环的事件分派器将选择这些事件并调用适当的插槽。这是Qt的力量 - 很多有用的东西可以为你做。

Sending a signal to such an object results in posting an event to the event queue of the thread the object is in. The event loop's event dispatcher will pick those events and call the appropriate slots. This is the power of Qt - a lot of useful stuff can be done for you.

请注意, 当前正忙线程的概念。线程执行那里存在的对象的短槽。如果你想在忙和不忙状态之间移动线程,那么你需要额外的代码。

Note that there is no notion of a "currently busy" thread. The threads execute short slots of the objects that live there. If you want to move threads between a "busy" and "not busy" states, then you'd need extra code for that.

另一种实现方式是从 QRunnable 派生并使用 QThreadPool 。这是另一个答案。

Another way of implementing it would be to derive from QRunnable and use QThreadPool. That's in another answer.

main.cpp

#include <QCoreApplication>
#include <QTextStream>
#include <QThread>
#include <QFile>
#include <cstdio>

class Notified : public QObject {
    Q_OBJECT
    QTextStream m_out;
public:
    Q_SLOT void notify(const QString & text) {
        m_out << "(" << this << ") " << text << endl;
    }
    Notified(QObject *parent = 0) : QObject(parent), m_out(stdout) {}
};

class Notifier : public QObject {
    Q_OBJECT
    Q_SIGNAL void notification(const QString &);
public:
    Notifier(QObject *parent = 0) : QObject(parent) {}
    void notifyLines(const QString & filePath) {
        QFile file(filePath);
        file.open(QIODevice::ReadOnly | QIODevice::Text);
        while (! file.atEnd()) {
            emit notification(file.readLine());
        }
        file.close();
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QObjectList notifieds;
    QList<QThread*> threads;
    Notifier notifier;

    for (int i = 0; i < 4; ++i) {
        QThread * thread = new QThread(&a); // thread owned by the application object
        Notified * notified = new Notified; // can't have an owner before it's moved to another thread
        notified->moveToThread(thread);
        thread->start();
        notifieds << notified;
        threads << thread;
        notified->connect(&notifier, SIGNAL(notification(QString)), SLOT(notify(QString)));
    }

    notifier.notifyLines("file.txt");

    foreach (QThread *thread, threads) {
        thread->quit();
        thread->wait();
    }
    foreach (QObject *notified, notifieds) delete notified;

    a.exit();
}

#include "main.moc"

这篇关于如何使用多线程创建一个简单的Qt控制台应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆