Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ QTimer不';t呼叫超时槽_C++_Qt_Qt4_Qthread_Qtimer - Fatal编程技术网

C++ QTimer不';t呼叫超时槽

C++ QTimer不';t呼叫超时槽,c++,qt,qt4,qthread,qtimer,C++,Qt,Qt4,Qthread,Qtimer,我试图在不同的QThread中使用QTimer,但无法连接到QTimer的timeout()插槽 我做错了什么 这是我的密码: extern MainWindow *mainClass; class myObj : public QObject { Q_OBJECT public: explicit myObj(QObject *parent = 0); ~myObj(); QThread workerThread; int percent;

我试图在不同的
QThread
中使用
QTimer
,但无法连接到
QTimer
timeout()
插槽

我做错了什么

这是我的密码:

extern MainWindow *mainClass;

class myObj : public QObject
{
    Q_OBJECT
public:
    explicit myObj(QObject *parent = 0);
    ~myObj();
    QThread workerThread;

    int percent;
    QTimer *percentTimer;

public slots:
    void doWork();
    void percentUpdate();
    void startFunction();

signals:
    void start();
    void UpdateResult();
};

myObj::myObj(QObject *parent) : QObject(parent)
{
    moveToThread(&workerThread);

    connect(&workerThread, SIGNAL(finished()), this, SLOT(deleteLater()));
    connect(this, SIGNAL(UpdateResult()), mainClass, SLOT(on_UpdateResult()));
    connect(&workerThread, SIGNAL(started()), this, SLOT(doWork()));
    connect(this, SIGNAL(start()), this, SLOT(startFunction()));

    percent++;
    percentTimer = new QTimer();
    percentTimer->moveToThread(&workerThread);
    percentTimer->setInterval(1000);
    connect(percentTimer, SIGNAL(timeout()), this,SLOT(percentUpdate()));

}

myObj::~myObj() {
    workerThread.quit();
    workerThread.wait();
    if (percentTimer) percentTimer->deleteLater();
}

void myObj::doWork()
{
    emit start();
    workerThread.exec();    
}

void myObj::startFunction()
{
    percentTimer->start();
    QThread::sleep(60);
    percentTimer->stop();    
}

void myObj::percentUpdate()
{
    qDebug() << "In Timer" << percent++;
    emit UpdateResult();

}
extern主窗口*mainClass;
MyObject类:公共QObject
{
Q_对象
公众:
显式myObj(QObject*parent=0);
~myObj();
QThread-workerThread;
整数百分比;
QTimer*percentTimer;
公众时段:
无效销钉();
void percentUpdate();
void startFunction();
信号:
void start();
void UpdateResult();
};
myObj::myObj(QObject*父对象):QObject(父对象)
{
moveToThread(&workerThread);
连接(&workerThread,SIGNAL(finished()),this,SLOT(deleteLater());
连接(此,信号(UpdateResult()),main类,插槽(在_UpdateResult()上);
连接(&workerThread,SIGNAL(started()),this,SLOT(doWork());
连接(这个,信号(start()),这个,插槽(startFunction());
百分比++;
percentTimer=新的QTimer();
percentTimer->moveToThread(&workerThread);
百分比计时器->设置间隔(1000);
连接(百分比计时器,信号(超时()),此,插槽(百分比更新());
}
myObj::~myObj(){
workerThread.quit();
workerThread.wait();
如果(percentTimer)percentTimer->deleteLater();
}
void myObj::doWork()
{
发射开始();
workerThread.exec();
}
void myObj::startFunction()
{
百分比计时器->开始();
QThread::sleep(60);
百分比计时器->停止();
}
void myObj::percentUpdate()
{

qDebug()首先,您应该共享
workerThread
,让
myObj
在其上下文中工作(在创建所需的连接后启动,因为连接到
start
信号的插槽可能不会被执行)。 您不应该使用
QThread::sleepFor
而是应该使用如下内容:

QEventLoop loop;
QTimer::singleShot(60000, &loop, SLOT(exit()));
loop.exec();
创建延迟,因为
QThread::sleepFor
会冻结整个线程执行。因此,不会处理绑定到此线程的任何事件


workerThread.exec()
在这里是无用的。

首先,您应该共享
workerThread
,让
myObj
在其上下文中工作(在创建所需的连接后启动它,因为连接到
start
信号的插槽可能不会被执行)。 您不应该使用
QThread::sleepFor
而是应该使用如下内容:

QEventLoop loop;
QTimer::singleShot(60000, &loop, SLOT(exit()));
loop.exec();
创建延迟,因为
QThread::sleepFor
会冻结整个线程执行。因此,不会处理绑定到此线程的任何事件


workerThread.exec()
在这里是无用的。

这是因为您试图从创建QTimer的线程以外的其他线程启动QTimer。使用QTimer和线程时,应非常小心地在将控制它的线程中创建QTimer

发件人:

在多线程应用程序中,可以在具有事件循环的任何线程中使用QTimer。若要从非GUI线程启动事件循环,请使用QThread::exec()。Qt使用计时器的线程关联来确定哪个线程将发出超时()信号。因此,必须在其线程中启动和停止计时器;无法从其他线程启动计时器

myObj::myObj(QObject *parent) : QObject(parent), percentTimer(nullptr)
{
    moveToThread(&workerThread);

    connect(&workerThread, SIGNAL(finished()), this, SLOT(deleteLater()));
    connect(this, SIGNAL(UpdateResult()), mainClass, SLOT(on_UpdateResult()));
    connect(&workerThread, SIGNAL(started()), this, SLOT(init()));
    connect(&workerThread, SIGNAL(started()), this, SLOT(doWork()));
    connect(this, SIGNAL(start()), this, SLOT(startFunction()));

    percent++;
}

void myObj::init() {
    percentTimer = new QTimer();
    percentTimer->setInterval(1000);
    connect(percentTimer, SIGNAL(timeout()), this, SLOT(percentUpdate()));
}
在您的情况下,
percentTimer=new QTimer();
是从主线程执行的(即使您以前使用过
moveToThread
,这仍然是执行它的主线程),而
doWork
start
信号是从
workerThread
发出的

例如,您可以从
workerThread
调用的
void init()
插槽执行
new QTimer
,而不是在构造函数中,以确保
QTimer
由正确的线程创建和拥有

myObj::myObj(QObject *parent) : QObject(parent), percentTimer(nullptr)
{
    moveToThread(&workerThread);

    connect(&workerThread, SIGNAL(finished()), this, SLOT(deleteLater()));
    connect(this, SIGNAL(UpdateResult()), mainClass, SLOT(on_UpdateResult()));
    connect(&workerThread, SIGNAL(started()), this, SLOT(init()));
    connect(&workerThread, SIGNAL(started()), this, SLOT(doWork()));
    connect(this, SIGNAL(start()), this, SLOT(startFunction()));

    percent++;
}

void myObj::init() {
    percentTimer = new QTimer();
    percentTimer->setInterval(1000);
    connect(percentTimer, SIGNAL(timeout()), this, SLOT(percentUpdate()));
}

这是因为您试图从创建QTimer的线程以外的其他线程启动QTimer。使用QTimer和线程时,应非常小心地在将控制它的线程中创建QTimer

发件人:

在多线程应用程序中,可以在具有事件循环的任何线程中使用QTimer。若要从非GUI线程启动事件循环,请使用QThread::exec()。Qt使用计时器的线程关联来确定哪个线程将发出超时()信号。因此,必须在其线程中启动和停止计时器;无法从其他线程启动计时器

myObj::myObj(QObject *parent) : QObject(parent), percentTimer(nullptr)
{
    moveToThread(&workerThread);

    connect(&workerThread, SIGNAL(finished()), this, SLOT(deleteLater()));
    connect(this, SIGNAL(UpdateResult()), mainClass, SLOT(on_UpdateResult()));
    connect(&workerThread, SIGNAL(started()), this, SLOT(init()));
    connect(&workerThread, SIGNAL(started()), this, SLOT(doWork()));
    connect(this, SIGNAL(start()), this, SLOT(startFunction()));

    percent++;
}

void myObj::init() {
    percentTimer = new QTimer();
    percentTimer->setInterval(1000);
    connect(percentTimer, SIGNAL(timeout()), this, SLOT(percentUpdate()));
}
在您的情况下,
percentTimer=new QTimer();
是从主线程执行的(即使您以前使用过
moveToThread
,这仍然是执行它的主线程),而
doWork
start
信号是从
workerThread
发出的

例如,您可以从
workerThread
调用的
void init()
插槽执行
new QTimer
,而不是在构造函数中,以确保
QTimer
由正确的线程创建和拥有

myObj::myObj(QObject *parent) : QObject(parent), percentTimer(nullptr)
{
    moveToThread(&workerThread);

    connect(&workerThread, SIGNAL(finished()), this, SLOT(deleteLater()));
    connect(this, SIGNAL(UpdateResult()), mainClass, SLOT(on_UpdateResult()));
    connect(&workerThread, SIGNAL(started()), this, SLOT(init()));
    connect(&workerThread, SIGNAL(started()), this, SLOT(doWork()));
    connect(this, SIGNAL(start()), this, SLOT(startFunction()));

    percent++;
}

void myObj::init() {
    percentTimer = new QTimer();
    percentTimer->setInterval(1000);
    connect(percentTimer, SIGNAL(timeout()), this, SLOT(percentUpdate()));
}

当您在调试器中单步执行此操作时会发生什么情况?首先在每个方法中放置一个断点。调用哪些断点,顺序如何?一切正常,除了在超时时从不调用插槽百分比更新@MrEricSir@MrEricSir,尝试在
percentTimer->moveToThread(…)之前移动
connect(percentTimer…
);
相同的结果@RealFresh、connect(&workerThread、SIGNAL(started())、percentTimer、SLOT(start())工作正常,但在我的应用程序中不起作用,因为我必须在某些时间间隔内启动、停止和更改间隔当问题陈述只是“它不起作用”时,很难提供解决方案。请回答您的问题,以便更完整地描述您预期会发生什么,以及这与实际结果之间的差异。请参阅,以获取有关什么是好的解释的提示。在调试器中单步执行此操作时会发生什么情况?从开始