QThread блокирует основное приложение - PullRequest
9 голосов
/ 09 июля 2010

У меня есть простой пользовательский интерфейс формы, в котором есть гнездо для кнопки, запускающей поток:

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

И метод run () выглядит следующим образом:

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

КогдаЯ нажимаю кнопку, которая вызывает LoadImage (), пользовательский интерфейс перестает отвечать на запросы.Я периодически вижу сообщение "ping" как вывод отладки, но пользовательский интерфейс зависает, ни на что не отвечает.Почему мой поток не работает отдельно?CameraThread получена как общедоступная QThread. Я использую gcc версии 4.4.3 (Ubuntu 4.4.3-4ubuntu5) с библиотеками QT и QT Creator из репозиториев Ubuntu 10.04 (x86).

Ответы [ 3 ]

30 голосов
/ 09 июля 2010

Краткий ответ: Запустите ваш поток, вызвав aThread->start();, а не run(), и убедитесь, что метод run () вашего потока защищен (не публично).

Пояснение

Вызов start() является правильным способом для запуска потока, поскольку он обеспечивает планирование приоритетов и фактически выполняет метод run() в своем собственном контексте потока.

Похоже, вы собираетесь загружать изображения в этой теме, поэтому я собираюсь включить несколько советов, прежде чем вы столкнетесь с ловушками, с которыми сталкиваются многие люди при использовании QThread

  1. Q Сам по себе поток - это не нить. Это всего лишь обертка вокруг нити, что приводит нас к ..
  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 по этой теме.

5 голосов
/ 09 июля 2010

Вы должны вызвать thread-> start () not run ... run - это точка входа для потока.Тема начинается со старта.Вы звоните прямо запустить, поэтому вы блокируете свой графический интерфейс.Проверьте документацию QThread.виртуальная пустота QThread :: run () защищена (не без причины)

0 голосов
/ 11 июля 2010

Я думаю, что проблема может быть в том, что вы не вызываете QtCore.QThread._init __ (self) в конструкторе. Я была такая же проблема. Также я думаю, что вы не должны переопределять функцию запуска, просто переопределите функцию run (). Это решило ту же проблему, что и у меня. Даже без каких-либо задержек sleep () окно должно реагировать.

...