【问题标题】:qt thread with movetothreadqt 线程与 movetothread
【发布时间】:2012-06-17 12:54:20
【问题描述】:

我正在尝试使用线程创建程序: 主要从一个循环开始。 当测试返回 true 时,我创建一个对象并希望该对象在另一个线程中工作 然后返回并开始测试。

QCoreApplication a(argc, argv);
while(true){
    Cmd cmd;
    cmd =db->select(cmd);
    if(cmd.isNull()){ 
        sleep(2);  
        continue ;
    }
    QThread *thread = new QThread( );
    process *class= new process ();
    class->moveToThread(thread);
    thread->start();

    qDebug() << " msg"; // this doesn't run until  class finish it's work 
}
return a.exec();

问题是当我启动新线程时,主线程停止并等待新线程完成。

【问题讨论】:

    标签: c++ multithreading qt


    【解决方案1】:

    规范的 Qt 方式如下所示:

     QThread* thread = new QThread( );
     Task* task = new Task();
    
     // move the task object to the thread BEFORE connecting any signal/slots
     task->moveToThread(thread);
    
     connect(thread, SIGNAL(started()), task, SLOT(doWork()));
     connect(task, SIGNAL(workFinished()), thread, SLOT(quit()));
    
     // automatically delete thread and task object when work is done:
     connect(task, SIGNAL(workFinished()), task, SLOT(deleteLater()));
     connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    
     thread->start();
    

    如果您不熟悉信号/槽,Task 类看起来像这样:

    class Task : public QObject
    {
    Q_OBJECT
    public:
        Task();
        ~Task();
    public slots:
        // doWork must emit workFinished when it is done.
        void doWork();
    signals:
        void workFinished();
    };
    

    【讨论】:

    • 谢谢它的工作。但现在我得到:获取 QObject:无法为位于不同线程中的父级创建子级。
    • 您必须从已经在目标线程中运行的Task 代码创建那些子代,或者在对象被移动到目标线程之前。
    • smerlin:感谢您提供非常好的答案。
    • 我想知道如果要向doWork()发送参数怎么办?您可以直接发送参数还是必须以其他方式传递它们。那么也许使用事件会更好。
    • @Trilarion:要么将参数传递给 Task 构造函数并将它们存储为成员变量,要么使用信号/槽系统。
    【解决方案2】:

    我不知道您是如何构建流程类的,但这并不是 moveToThread 真正的工作方式。 moveToThread 函数告诉 QT 任何插槽都需要在新线程中执行,而不是在发出信号的线程中执行。 (编辑:实际上,我现在记得它默认为创建对象的胎面)

    此外,如果您从构造函数中在进程类中执行工作,它也不会在新线程中运行。

    让您的进程类在新线程中执行的最简单方法是从 QThread 派生它并覆盖 run 方法。那么你根本不需要调用 move 到线程。

    【讨论】:

    • 好的,谢谢您的回复,我认为 movetothread 可以完成这项工作。我会用你的想法
    • 只有在你的工作代码中不想要任何信号或槽的情况下,它才会这样工作。只要你这样做,就更容易从 QObject 派生。您通常希望每个线程有多个工作 QObject。为每个要完成的任务生成一个线程的通常方法是,好吧,脑死。它在不需要的地方增加了线程切换开销。
    • 你可以作弊并从 QThread 派生并为其添加信号和插槽,但这变得非常不直观。 QThread 是一个控制线程的对象。当您在线程本身中运行 QThread 的插槽时,您创建了一个既是线程控制器又是线程的科学怪人。而且,它再次成为一个单一用途的线程。
    • 从 QThread 派生的唯一原因是......好吧,没有理由。 QThread 旋转一个事件循环,您可以随时将 QObject 移动到它。这样,您的工作对象的生命周期与线程的生命周期不同。如果还有更多工作要做,为什么不重用线程呢?等等...... Qt 的文档完全没有解释这一切的意义:(
    • @KubaOber:曾经是有原因的...曾几何时QThread是一个抽象类,你必须派生和重新实现run()并自己调用exec()...但好在QThread 现在提供了run() 本身的实现。
    猜你喜欢
    • 1970-01-01
    • 2013-10-18
    • 2018-11-10
    • 1970-01-01
    • 2011-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多