2013-02-06 57 views
0

这是QThread的子类的run方法:Qt的线程和循环问题

void crono::Controller::run() { 

    //initialise timer 
    int *i = & this->model->seconds_elapsed; 

    for (*i = 0; *i < this->model->seconds_total; (*i)++) { 

    //calculate current seconds/minutes/hours elapsed starting from seconds_elapsed (*i) 
    this->model->tick(); 

    //should display in the form the time elapsed 
    this->vista->showTime(); 
    sleep(1000); 


    } 

    Beep(1000, 500); //beep when all is over 

} 

控制器更新模型值。

QT表单在开始时打开,我想在主应用程序线程中。

问题是,对debug * i = 0和seconds_total = X> 0的鄙视,循环只执行一次,在第一次调试停止后(它没有结束),表单弹出但没有任何发生。

我唯一能猜到的是控制器线程失去了优先级,从来没有再次获得CPU。

如何避免这种情况?

编辑 我使用QTimer,与倒霉尝试。

我声明更新为公共时隙,然后这样来实现:

void crono::Controller::update() { 

    this->modello->tick(); 
    this->vista->showTime(); 

    //eventually stop at some point (pointer to timer and timer->stop()? 
    //... 
    //Beep(1000, 500); 
} 

我插入QTimer在控制器(线程)对象,而不是循环周期:

void crono::Controller::run() { 

    //inizializzo timer 
    int *i = & this->modello->secondi_trascorsi; 

    QTimer *timer = new QTimer(this); 
    connect(timer, SIGNAL(timeout()),this, SLOT(update())); 
    timer->start(1000); 


} 

我不知道为什么,但update()方法永远不会被调用,而不是被称为无限次数。为什么?

+0

不,我不认为这可能是问题。调试或添加一些调试日志记录来检查是否达到睡眠子句。也许其他方法之一导致无限循环? –

+0

“//应该以流逝的时间的形式显示” - 您确定没有直接从线程访问GUI,而是仅通过信号/插槽来访问GUI? – borisbn

+2

我强烈建议保持QThread和实现彼此分离,即不要继承QThread(阅读Zaiborg的链接)。如果你真的重新实现'QThread :: run()',你需要在'run()'方法的末尾调用'exec()',否则任何事件(包括信号)都不会被线程处理。 –

回答

2

正如Tim Meyer在他的评论中指出的,您需要在QThread::run()实现的末尾调用QThread:exec(),这是为了启动线程的事件循环,这是Signal/Slot机制的工作所必需的。

但是,它好像是you're doing it wrong

+0

我做错了,因为博客文章暗示要继承QThread/meh – alessiop86

+2

我想即使是Qt文档也暗示了一段时间。 非常好的示例:http://qt-project.org/doc/qt-4.8/QThread.html#details –

1

我敢肯定,你的循环应该是这样的:

//initialize timer 
int elapsed = this->model->seconds_elapsed; 

for (int i = 0; i < elapsed; i++) 

我认为没有必要使用指针。把事情简单化。

如果这仍然不起作用,那么你做的其他事情不对,而且你的代码并不明显。

此外线程信令不使用sleep完成。为了线程信号的目的,您应该查看线程事件,如信号量或条件变量。

如果您想定期更新值,为什么不使用QTimer?

sleep只有很少的有效用途,我相信你正在解决一个不需要睡眠的问题。

+0

为了在每个周期更新模型的状态需要一个指针 – alessiop86

2

首先,QThread不应该由于几乎任何原因而被继承。

线程通常会像有描述来完成:http://qt-project.org/doc/qt-4.8/QThread.html#details

如果你只需要线程来算一段时间,一段时间后做的东西,也许你可以使用QTimer代替和QTimer::timeout()信号连接到您的插槽显示已用时间。

4

一个常见的混淆是QThread运行在它自己的单独线程中。不是这种情况;相反,QThread会在其控制的子线程中启动事件循环。 QThread很容易被称为QThreadManager

总之,不要子集QThread,因为您创建的功能驻留在主线程(而不是QThread处理的线程)。使用连接到started()信号的插槽创建一个QObject子类。然后使用moveToThread()并在QThread实例上调用run()

另外,您不能直接从子线程调用主线程函数。你需要一个排队连接信号给主线程中的对象来显示对话框。