我正在尝试实现一些小应用程序,这是一个gui应用程序,并且有一些繁重的工作要做,作为其中一个主要任务。显然我正在把这个“工作”放到一个单独的线程中并通过在这个obj上调用start fnc来启动这个线程。不幸的是没有任何反应。另一方面,当调用实现的fnc运行计算而不是启动时,它们应该执行,尽管当然它们与gui在同一个线程中。怎么办?
所以我有继承QThread的类:
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);
};
当我尝试启动新线程时,这是来自gui线程的片段:
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
更新:
我做的变化很小,现在使用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)
如果你在线程上调用wait(),GUI就会阻塞,因为这会等待线程完成,而且在这种情况下你还没有指定等待的超时。
现在关于初始问题(当你不调用wait()时),我在类似的场景中成功使用了QThread。我不知道你的代码有什么问题,但我要检查的是你的执行是否在其他地方没有挂起,比如调用
(parent_->*fnc_)(paths_,search_depth_);
因此,可能在此调用之前和之后插入一些日志/调试消息,并且在此处调用的函数中也可能有助于隔离问题。至少你会知道是否调用了run()方法。例如:
qDebug() << "In thread.run()";
(parent_->*fnc_)(paths_,search_depth_);
qDebug() << "In thread.run(), calculations are done";
此外,我发现您使用GUI对象(Dir_File_Select_Dialog)执行计算是可疑的。这在Qt中是不正常的,Gui对象通常应该在GUI线程中使用。为什么不直接在运行中实现计算?或者至少将其移动到非GUI对象,只是为了确保并将GUI实现与后台操作分开。
答案 1 :(得分:1)
我不知道您的代码是如何实际完成的,但作为第一步,我建议您遵循QThread Qt文档新版本末尾建议的最佳做法:
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);
答案 2 :(得分:0)
如果您呼叫等待,GUI将被阻止。
如果此程序在您启动时挂起,则问题出现在此调用中:(parent_->*fnc_)(paths_,search_depth_);
您可以在此呼叫之前和之后发出qDebug呼叫。