2010-07-09 4 views
8

У меня есть простой вид пользовательского интерфейса, который имеет слот для кнопки, начиная нить:QThread блокировки основного приложения

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

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

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

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

ответ

27

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

Объяснение

Calling start() is the correct way, чтобы начать нить, так как она обеспечивает приоритет планирования и фактически выполняет метод run() в своем собственном контексте потока.

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

  1. сам QThread не Тема. Это просто оболочка вокруг нити, это приводит нас к ..
  2. сигналы/слоты, определенные в CameraThread класса не обязательно работать в контекст потока, помните только метод запуска() и методы, вызываемые из него работают в отдельном потоке.

ИМХО, подклассов 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 blog по этой теме.

+0

Документация QT объясняет использование QThread путем подкласса. Почему это плохая идея? –

+1

@Atilla - если вы читаете ссылку в блоге QT в ответе Кейси, вы найдете ее под названием «Вы делаете это неправильно ...». Это дискуссия о том, почему документация Qt о подклассификации QThread была неправильным способом создания потоков.Кроме того, если я правильно прочитал запись в блоге, это тот, кто написал оригинальную документацию Qt. –

+2

Да, это правильно. В основном, документация Qt вводит в заблуждение и, следовательно, приводит многих людей к хакерским вещам (например, movetoThread (this) в конструкторе Qthread), которые вызывают проблемы в строке. Надеемся, что документы скоро будут обновлены. – Casey

4

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

-1

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

+1

Нет, моя проблема заключалась в вызове run() вместо начала(). Я уже преодолел run(). –

Смежные вопросы