使用 Qt 线程的最小示例? [英] Minimal Example to use Qt Threads?

查看:48
本文介绍了使用 Qt 线程的最小示例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在寻找 Qt 线程的简洁示例,但我发现的只是复杂的令人眼花缭乱",声称展示了 QThreads 的工作原理,但它们实在是太难弄清楚了.

I was looking for a concise example of Qt threading, and all I found was complex "eye-candy" that claimed to show how QThreads work, but they were simply too much to figure out.

我接受了 Zen 的回答,因为他向我展示了我的尝试遗漏的确切内容,然后添加了我自己的作为我想要看到的示例.点击此处跳转:https://stackoverflow.com/a/34561122/3491308

I accepted Zen's answer because he showed me the exact thing that my attempts were missing, then added my own to be the example that I wanted to see. Click here to skip to it: https://stackoverflow.com/a/34561122/3491308

我原来的问题如下:

看来我一定遗漏了一些东西,但我似乎无法像我认为应该的那样完成这项工作.我的完整应用程序需要有两个或三个线程,所有线程(几乎)一起启动并永远运行:

It seems I must be missing something, but I just can't seem to make this work like I think it ought to. My complete application needs to have two or three threads, all of which start (almost) together and run forever:

  • 图形用户界面
    • 在启动其他两个线程来处理它们之前,从文件中加载一堆对象.
    • 具有 TimeCriticalPriority 和周期性 QTimer中断",试图将 PC 用作比我开始时更强大的嵌入式系统.这个项目一开始是完全嵌入的,很快就变得过于复杂而无法在那里进行管理.
    • 连接到仍嵌入的项目部分.

    核心功能当然是在实时处理线程中,另外两个只是简单地调整它的工作方式.因此,在实时处理器运行时,会根据用户在 GUI 中的操作创建、修改和销毁处理对象,其中一些对象中的数据也由 USB 生成和使用.

    The core functionality, of course, is in the realtime processing thread, and the other two are simply to adjust how it works. So there are processing objects being created, modified, and destroyed while the realtime processor is running, based on the user's actions in the GUI, and the data inside some of those objects is being produced and consumed by USB also.

    我一直在寻找有关如何在 Qt 中使用线程的示例,但我不断得到复杂的令人眼花缭乱"的应用程序,这些应用程序使线程部分变得混乱.我尽我最大的努力尝试解释它们并编写我自己的,但我一直在 Qt 中遇到段错误,我的小操场"项目说我什至没有得到第二个线程:

    I keep looking for examples of how to use threads in Qt, but I keep getting complex "eye candy"-type applications that clutter up the threading part. I do my best to try and interpret them and write my own, but I keep getting segfaults in Qt itself and my small "playground" project says that I'm not even getting a second thread:

    #ifndef MAIN_H
    #define MAIN_H
    
    #include <QtWidgets>
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    public:
        MainWindow(QWidget* parent = 0);
        ~MainWindow() {}
    private:
        QObject* mythingy;
    private slots:
        void deleteObject(QObject* thingy);
    };
    
    class Worker : public QObject
    {
        Q_OBJECT
    public:
        Worker(QObject* thingy, QObject* parent = 0);
    private:
        QObject* mythingy;
    signals:
        void deleteObject(QObject* thingy);
    private slots:
        void doWork();
    };
    
    #endif // MAIN_H
    
    /***************
    *** main.cpp ***
    ***************/
    #include "main.h"
    #include <QApplication>
    
    int main(int argc, char* argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
        return a.exec();
    }
    
    
    
    MainWindow::MainWindow(QWidget* parent)
        : QMainWindow(parent)
    {
        mythingy = new QObject(this);
        QThread* thisthread = this->thread();
        QThread* mainthread = QCoreApplication::instance()->thread();
        //breakpoint here to check thisthread and mainthread
        Worker* worker = new Worker(mythingy, this);
        connect(worker, SIGNAL(deleteObject(QObject*)), this, SLOT(deleteObject(QObject*)));
    }
    
    void MainWindow::deleteObject(QObject* thingy)
    {
        QThread* thisthread = this->thread();
        QThread* mainthread = QCoreApplication::instance()->thread();
        //breakpoint here to check thisthread and mainthread
        delete thingy;
    }
    
    
    
    Worker::Worker(QObject* thingy, QObject* parent)
        : QObject(parent)
    {
        mythingy = thingy;
        QThread* thread = new QThread(this);
        this->moveToThread(thread);
    
        //use a timer to allow the constructor to exit
        QTimer* timer = new QTimer(this);
        timer->setSingleShot(true);
        timer->start(1000);
        connect(timer, SIGNAL(timeout()), this, SLOT(doWork()));
    
        QThread* thisthread = this->thread();
        QThread* mainthread = QCoreApplication::instance()->thread();
        //breakpoint here to check thisthread and mainthread
        thread->start();
    }
    
    void Worker::doWork()
    {
        QThread* thisthread = this->thread();
        QThread* mainthread = QCoreApplication::instance()->thread();
        //breakpoint here to check thisthread and mainthread
        deleteObject(mythingy);
    }
    

    如果有人可以根据我对项目的描述,发布一个如何正确使用 QThreads 的示例,并且尽可能少杂乱(如果可能的话,最好比我的短),我将不胜感激.

    If someone can post an example of how to do QThreads right, given my description of the project, and with as little clutter as possible (preferably shorter than mine if possible), I'd greatly appreciate it.

    根据 Zen 的回答,这似乎也有效:

    Based on Zen's answer, this seems to work too:

    MainWindow::MainWindow(QWidget* parent)
        : QMainWindow(parent)
    {
        mythingy = new QObject(this);
        QThread* thisthread = this->thread();
        QThread* mainthread = QCoreApplication::instance()->thread();
        Worker* worker = new Worker(mythingy, this);
    }
    
    Worker::Worker(QObject* thingy, QObject* parent)
        : QObject(0)    //no real parent, so we can move to a different thread
    {
        mythingy = thingy;
    
        QTimer* timer = new QTimer(this);
        timer->setSingleShot(true);
        timer->start(1000);
        connect(timer, SIGNAL(timeout()), this, SLOT(doWork()));
    
        QThread* thread = new QThread(parent);
        this->moveToThread(thread);
        thread->start();
    }
    
    void Worker::doWork()
    {
        QThread* thisthread = this->thread();
        QThread* mainthread = QCoreApplication::instance()->thread();
        delete mythingy;
    }
    

    仍然在构造函数内部移动自己,现在直接删除对象而不是告诉所有者的线程这样做.(请记住,在完整项目中,所有者已经将对象标记为删除,但实际上并未这样做,因为其他线程可能正在使用它)

    Still moving myself inside the constructor, and now deleting the object directly instead of telling the owner's thread to do it. (remember in the full project that the owner has already marked the object for deletion but refrained from actually doing so because the other thread might be using it)

    有什么问题吗?

    推荐答案

    1. 不能移动带有父级的对象.所以代替Worker* worker = new Worker(mythingy, this);,你应该使用Worker* worker = new Worker(mythingy);
    2.您不能为不同线程中的父级创建子级.

    1.you cannot move objects with a parent. So instead Worker* worker = new Worker(mythingy, this);, you should use Worker* worker = new Worker(mythingy);
    2.you cannot create children for a parent that is in a different thread.

    MainWindow::MainWindow(QWidget* parent)
        : QMainWindow(parent)
    {
        mythingy = new QObject(this);
        QThread* thisthread = this->thread();
        QThread* mainthread = QCoreApplication::instance()->thread();
        //breakpoint here to check thisthread and mainthread
        //*****************
        Worker* worker = new Worker(mythingy);
        QThread* thread = new QThread();
        worker->moveToThread(thread);
        thread->start();
        //*****************
        connect(worker, SIGNAL(deleteObject(QObject*)), this, SLOT(deleteObject(QObject*)));
    }
    
    Worker::Worker(QObject* thingy, QObject* parent)
        : QObject(parent)
    {
        mythingy = thingy;
    //    QThread* thread = new QThread(this);
    //    this->moveToThread(thread);
    
        //use a timer to allow the constructor to exit
        QTimer* timer = new QTimer(this);
        timer->setSingleShot(true);
        timer->start(1000);
        connect(timer, SIGNAL(timeout()), this, SLOT(doWork()));
    
    //    QThread* thisthread = this->thread();
    //    QThread* mainthread = QCoreApplication::instance()->thread();
        //breakpoint here to check thisthread and mainthread
    //    thread->start();
    }
    

    一个对象的槽总是由它所在的线程执行.所以,因为你从来没有移动MainWindow,所以没有必要在MainWindow::deleteObject中检查它的线程.例如:

    The slots of an object is always executed by the thread it lives in. So, since you have never move MainWindow, there is no need to check its thread in MainWindow::deleteObject. For example:

    Worker* worker = new Worker(mythingy);
    QThread* thread = new QThread();
    worker->moveToThread(thread);
    thread->start();
    
    //wrong: directly invoking doWork in mainthread    
    worker->doWork();
    
    //correct: through signal-slot mechanics
    connect(this, SIGNAL(startWork()), worker, SLOT(doWork()));
    

    这篇关于使用 Qt 线程的最小示例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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