QThread 阻塞主应用程序

发布于 2024-09-09 00:16:22 字数 510 浏览 0 评论 0原文

我有一个简单的表单 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。

I have a simple form UI that has a slot for a button, starting a thread:

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

And the run() method looks like this:

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

When I click the button that calls LoadImage(), the UI becomes unresponsive. I periodically see the "ping" message as the debug output but the UI hangs, does not respond to anything.
Why is my thread not running separately? CameraThread derived as public QThread
I am using gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) with QT libraries and QT Creator from Ubuntu 10.04(x86) repositories.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我偏爱纯白色 2024-09-16 00:16:22

简短回答:通过调用 aThread->start(); 而不是 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 博客

Short answer: Start your thread by calling aThread->start(); not run(), and make sure you thread's run() method is protected (not public).

Explanation

Calling start() is the correct way to start the thread, as it provides priority scheduling and actually executes the run() method in its own thread context.

It looks like you are going to be loading images in this thread, so I'm going to include some tips before you run into pitfalls many people fall into while using QThread

  1. QThread itself is not a thread. It is just a wrapper around a thread, this brings us to..
  2. signals/slots defined in the CameraThread class will not necessarily run in the thread's context, remember only the run() method and methods called from it are running in a separate thread.

IMHO, subclassing QThread in the majority of cases is not the way to go. You can do it much simpler with the following code, and it will save you many headaches.

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();
}

Also read the Qt blog regarding this topic.

好久不见√ 2024-09-16 00:16:22

你必须调用 thread->start() 而不是 run...run 是线程的入口点。线程通过 start 启动。你直接调用 run,这就是你阻止你的 gui 的原因。检查 QThread 的文档。 virtual void QThread::run() 受到保护(不是没有原因的)

You have to call thread->start() not run... run is an entry point for thread. Thread is started with start. You call directly run, that's why you block your gui. Check documentation of QThread. virtual void QThread::run() is protected (not without a reason)

半世晨晓 2024-09-16 00:16:22

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

I think the problem could be that you are not calling QtCore.QThread._init__(self) in the constructor. I had the same issue. Also I think you should not override the start function, just override the run() function. This solved the same issue that I was having. Even without any sleep() delays, the window should be responsive.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文