start不会调用run

时间:2012-04-01 10:11:57

标签: c++ qt

我正在尝试实现一些小应用程序,这是一个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.

3 个答案:

答案 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呼叫。