10

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

void MainWindow::LoadImage()
{
    aThread->run();
}

run() 方法如下所示:

void CameraThread::run()
{
    qDebug("Staring Thread");
    while(1)
    {
        qDebug("ping");
        QThread::sleep(1);
    }
}

当我单击调用 LoadImage() 的按钮时,UI 变得无响应。我定期将“ping”消息视为调试输出,但 UI 挂起,不响应任何内容。为什么我的线程没有单独运行?CameraThread 派生为公共 QThread 我正在使用 gcc 版本 4.4.3 (Ubuntu 4.4.3-4ubuntu5) 以及来自 Ubuntu 10.04(x86) 存储库的 QT 库和 QT Creator。

4

3 回答 3

33

简短回答:通过调用aThread->start();not启动线程run(),并确保线程的 run() 方法受到保护(不公开)。

解释

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

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

  1. QThread 本身不是线程。它只是一个线程的包装器,这将我们带到..
  2. 类中定义的信号/槽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();
}

另请阅读有关此主题的Qt 博客。

于 2010-07-09T15:15:07.793 回答
5

您必须调用 thread->start() not run... run 是线程的入口点。线程以 start 开始。你直接调用run,这就是你阻止你的gui的原因。检查 QThread 的文档。virtual void QThread::run() 受保护(并非没有理由)

于 2010-07-09T14:58:54.153 回答
-1

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

于 2010-07-11T03:02:49.850 回答