2012-04-01 3 views
0

Я пытаюсь реализовать небольшое приложение, которое является графическим приложением, и имеет некоторую тяжелую работу, чтобы сделать его одной из основных задач. Очевидно, я помещаю эту «работу» в отдельный поток и запускаю этот поток, вызывая start fnc на этом объекте. К сожалению, ничего не происходит. С другой стороны, когда вместо запуска я вызываю выполненные вычисления fnc run, выполняются так, как они должны, хотя, конечно, в том же потоке, что и gui. Что делать?
Так что у меня класс наследующий QThread:start не вызывает запуск

class Working_Thread : public QThread 
{ 
    Q_OBJECT 
public: 
    typedef boost::filesystem3::path path_t; 

private: 
    bool& cancel_flag_; 
    const std::set<path_t>& paths_; 
    int search_depth_; 
    typedef void (Dir_File_Select_Dialog::*fnc_ptr)(const std::set<path_t>&,int); 
    fnc_ptr fnc_; 
    Dir_File_Select_Dialog* parent_; 
protected: 
    void run() 
    { 

     (parent_->*fnc_)(paths_,search_depth_); 
    } 
public: 

    Working_Thread(bool& cancel_flag,const std::set<path_t>&,int&,fnc_ptr fnc,Dir_File_Select_Dialog* parent); 


}; 

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

Working_Thread* working_thread = new Working_Thread(cancel_flag,paths,search_depth,&Dir_File_Select_Dialog::extract_files_,this); 
     working_thread->start();//this desn't invoke run fnc 

но когда я делаю:

working_thread->run();//this will perform computations although in gui thread 

UPDATE:
Небольшое изменение, которое я сделал, которое теперь выполняет вычисления при использовании start fnc, но оно по-прежнему блокирует GUI.

Working_Thread* working_thread = new Working_Thread(cancel_flag,paths,search_depth,&Dir_File_Select_Dialog::extract_files_,this); 
    working_thread->start();//hangs 
    working_thread->wait();//when I call wait here computation is performed but GUI is blocked. 
+0

Некоторые примечания: 1. Как вы понимаете, что запуск был/не был вызван? 2. Почему ваш объект GUI выполняет некоторые вычисления? Связаны ли они с графическим интерфейсом? Понимаете ли вы, что все GUI-операции должны вызываться в потоке графического интерфейса, и только каждая часть Qt не является потокобезопасной? – Lol4t0

+0

@ Lol4t0 1. run не был вызван, потому что я не вижу никакого эффекта, никакие результаты не отображаются на представлении, в отличие от того, когда я запускаю его напрямую. 2. Gui не выполняет никаких вычислений, откуда вы это понимаете, и да, я понимаю. – smallB

+0

Попробуйте добавить простой отладочный вывод для работы. Если вы хотите изменить вид, это означает, что вы уже изменили _perform_ Gui в другом потоке. – Lol4t0

ответ

1

Я не знаю, как ваш код на самом деле сделан, но в качестве первого шага я предлагаю вам следовать передовой практике предложила в конце нового пересмотра документации Qt в QThread:

http://qt-project.org/doc/qt-4.8/QThread.html (ищите внизу этой страницы)

для подобной обучающей программы вы также можете проверить эту статью: http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

Каждый раз, когда я пытался сразу сделать мое лечение в QThread я закончил тем, что имел большие проблемы с нитями (большинство время, обработка, выполняемая в протекторах звонящего). Эта документация была добавлена ​​в 4.8, а примеры, представленные в документации предыдущих версий, были пропущены.

(код копируется из документации Qt) Рассмотрим следующий шаблон в качестве пути по умолчанию для использования QThread:

class Worker : public QObject 
{ 
Q_OBJECT 

public slots: 
void doWork() { 
/* ... */ 
} 
}; 

/* ... */ 
QThread *thread = new QThread; 
Worker *worker = new Worker; 
//obj is a pointer to a QObject that will trigger the work to start. It could just be this 
connect(obj, SIGNAL(startWork()), worker, SLOT(doWork())); 
worker->moveToThread(thread); 
thread->start(); 
//obj will need to emit startWork() to get the work going. 

В качестве альтернативы, вы можете сделать:

//based on the same Worker class as above: 

/* ... */ 
QThread *thread = new QThread; 
Worker *worker = new Worker; 
worker->moveToThread(thread); 
thread->start(); 
QMetaObject::invokeMethod(worker, "doWork", Qt::QueuedConnection); 
+0

#Marc привет, спасибо за ваш ответ. Принят, хотя даже после прочтения этих двух веб-сайтов я все еще запутался из-за того, что, по-видимому, не было никакого определенного вывода по этому вопросу. – smallB

+0

#smallB Согласился, что эта тема довольно сбивает с толку устаревшей документации, приводящей к неправильным решениям. Тем не менее, когда я переключил свой существующий код на эту архитектуру, он решил много проблем, похожих на ваши. ура! – Marc

1

Это нормально, что GUI блоки, если вы звоните Wait() на волоске, потому что это будет ждать завершения потока, а также вы не указали тайм-аут для ожидания в этом случае.

Теперь о первоначальной проблеме (когда вы не вызываете wait()), я использовал QThread успешно в подобных сценариях. Я не знаю, хотя то, что неправильно в вашем коде, но то, что я хотел бы проверить, если ваше исполнение не висит в других местах, например, в вызове

(parent_->*fnc_)(paths_,search_depth_); 

Так может быть, вставив некоторые журнал/отладки сообщения перед и после этого вызова, а также в функции, которая вызывается здесь, может помочь изолировать проблему. По крайней мере, тогда вы узнаете, вызван ли метод run() или нет. Например:

qDebug() << "In thread.run()"; 
(parent_->*fnc_)(paths_,search_depth_); 
qDebug() << "In thread.run(), calculations are done"; 

Также я считаю подозрительным, что вы выполняете вычисления с использованием графического объекта (Dir_File_Select_Dialog). Это не нормально в Qt, объекты Gui обычно должны использоваться в потоке GUI. Почему бы не выполнить вычисления непосредственно в run? Или, по крайней мере, переместите его на объект без GUI, чтобы быть уверенным, и сохраняйте реализацию GUI отдельно от фоновых операций.

0

Если вы вызываете wait, GUI будет заблокирован.

Если эта программа зависает, когда вы начинаете, кажется, что проблема в этом вызове: (parent_->*fnc_)(paths_,search_depth_); Вы можете поместить вызов qDebug непосредственно перед этим и после этого вызова.

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