3

所以我有一个有 2 个插槽的工作类:StartWork() 和 StopWork(),StartWork() 运行一个无限循环(它只是不停地读取和读取相机输入),而 StopWork() 方法只是设置一个布尔值变量为假(因此 StartWork() 内的循环停止)。

根据 QThread 文档,现在使用它们的最佳方法不是通过子类化,而是将工作人员移动到线程中,这就是我所做的。问题是,来自线程的started() 信号被调用,但finished() 信号永远不会被调用。

工人阶级插槽:

无效的开始工作(){运行=真;while(running){ 做工作;}}

无效停止工作(){运行=假;}

QThread初始化和信号/槽连接:

thread = new QThread();
worker = new Worker();
worker.moveToThread(thread);

QObject::connect(thread, SIGNAL(started()), worker, SLOT(StartWork()));
QObject::connect(thread, SIGNAL(finished()), worker, SLOT(StopWork()));

在我的 QPushButton 上我这样做:

if(pushStartStop->text().toLower() == "start")
{
    pushStartStop->setText("Stop");
    thread->start();
}
else
{
    pushStartStop->setText("Start");
    thread->quit();
}

thread->start() 工作正常,StartWork() 被调用,一切都很漂亮(GUI 运行没有块等)。

但是 thread->quit() 没有做任何事情,它被调用(因为按钮改变了文本)但就是这样。如果我只是调用 worker->StopWork() 它可以工作,但是我无法再次启动它。

我试过用 thread->exit(); 但结果是一样的。我也知道子类化的作品,但它看起来更丑陋,根据最近的 Qt 文档,子类化不再是最佳的。

提前致谢。

4

1 回答 1

5

你有一个永远的循环:

void StartWork()
{
    running = true;
    while(running)
    {
        do work;
    }
}

这个函数会循环,所以线程的事件循环在发出之后就被阻塞了started()。因此,finished()不能发射。

解决方案1:

添加功能

void DoWork()
{
    if(running)
    {
        do work
    }
}

给工人,改变

void StartWork()
{
    running = true;
}

然后,只需连接DoWork到线程中的计时器。

解决方案2:

改变功能

void StartWork()
{
    running = true;
    while(running)
    {
        do work;
        QCoreApplication::processEvents();
    }
}

使用此解决方案,您将不得不在工作人员停止其工作时重新启动线程(StopWork()将强制此函数完成,因此事件循环将没有要处理的事件并且线程将完成)。

于 2012-10-17T20:07:55.377 回答