Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ QThread阻塞主应用程序_C++_Qt_Multithreading_Qthread - Fatal编程技术网

C++ QThread阻塞主应用程序

C++ QThread阻塞主应用程序,c++,qt,multithreading,qthread,C++,Qt,Multithreading,Qthread,我有一个简单的表单UI,它有一个按钮槽,启动一个线程: void MainWindow::LoadImage() { aThread->run(); } run()方法如下所示: void CameraThread::run() { qDebug("Staring Thread"); while(1) { qDebug("ping"); QThread::sleep(1); } } 当我单击调用LoadImage(

我有一个简单的表单UI,它有一个按钮槽,启动一个线程:

void MainWindow::LoadImage()
{
    aThread->run();
}
run()方法如下所示:

void CameraThread::run()
{
    qDebug("Staring Thread");
    while(1)
    {
        qDebug("ping");
        QThread::sleep(1);
    }
}
当我单击调用LoadImage()的按钮时,UI将变得无响应。我周期性地将“ping”消息视为调试输出,但UI挂起,没有任何响应。 为什么我的线程没有单独运行?派生为公共QThread的CameraThread
我正在使用gcc版本4.4.3(Ubuntu 4.4.3-4ubuntu5)和来自Ubuntu 10.04(x86)存储库的QT库和QT创建者。

您必须调用线程->开始(),而不是运行。。。run是线程的入口点。线程以start开始。您可以直接调用run,这就是为什么要阻止gui。检查QThread的文档。virtual void QThread::run()受保护(并非没有原因)

简短回答:通过调用
aThread->Start()启动线程
运行()
,并确保线程的run()方法受保护(非公共)

解释

启动线程,因为它提供优先级调度,并在自己的线程上下文中实际执行
run()
方法

看起来您将在这个线程中加载图像,所以在您遇到许多人在使用QThread时遇到的陷阱之前,我将提供一些提示

  • QThread本身不是一个线程。它只是一个围绕线程的包装器,这让我们想到
  • CameraThread
    类中定义的信号/插槽不一定在线程的上下文中运行,请记住,只有run()方法和从中调用的方法在单独的线程中运行
  • 依我看,在大多数情况下,将QThread子类化是而不是的方向。使用下面的代码,您可以做得更简单,并且它将为您节省许多麻烦

    class ImageLoader : public QObject {
    Q_OBJECT
    public slots:
        void doWork() 
        {
            // do work
        }
    };
    
    void MainWindow::MainWindow(/*params*/) 
    {
      ImageLoader loader;
      QThread thread;
      loader.moveToThread( &thread );
      connect( this, SIGNAL( loadImage() ), &loader ,SLOT( doWork() ) );
      thread.start();
      // other initialization
    }
    void MainWindow::LoadImage()
    {
       emit loadImage();
    }
    

    另外,请阅读与此主题相关的。

    我认为问题可能是您没有在构造函数中调用QtCore.QThread.\u init\uuuuself。我也有同样的问题。另外,我认为不应该重写start函数,而应该重写run()函数。这解决了我遇到的同样问题。即使没有任何sleep()延迟,窗口也应该响应。

    QT文档通过子类化解释了QThread的用法。为什么这是个坏主意?@Atilla-如果你阅读Casey回答中的QT博客链接,你会发现它的标题是“你做错了…”。这是关于为什么Qt关于子类化QThread的文档不是执行线程的正确方法的讨论。另外,如果我正确阅读了博客条目,那么它是由编写原始Qt文档的人写的。是的,这是正确的。基本上,Qt文档是误导性的,因此导致许多人做了一些令人讨厌的事情(比如Qthread构造函数中的movetoThread(这一点)),这会导致后续问题。希望文档很快就会更新。@photo_tom,@Casey,谢谢你们两位的澄清。在我的例子中,我的独立线程没有任何插槽,应该在自定义循环(连续轮询硬件)中运行,并且只需要偶尔通知主应用程序。所以在我的例子中,我相信子类化是正确的方法。我知道这是一个长期的死问题,但我不同意将QThread对象子类化为正确的方法。。。仍然创建QObject和
    threadInstance.moveToThread(myObjInstance)但是只要有一个插槽,当被调用时它将永远循环(或者直到某个条件变量从另一个sig/插槽连接被更改)。这还有一个额外的好处,就是可能使用同一个线程来做更多的事情,而不仅仅是一个对象工作(你可以在一个单独的线程中创建更多的对象),只要你在cont循环中执行
    processEvents
    ,一切都会很好。不,我的问题是调用run()而不是start()。我已经重写了run()。