首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >暂停和恢复QThread

暂停和恢复QThread
EN

Stack Overflow用户
提问于 2012-01-31 15:20:58
回答 2查看 9.8K关注 0票数 6

我最近开始学习QThreads,我有一个程序,它在一个单独的线程中运行一个4小时长的循环(这样我就可以继续使用图形用户界面)。我想要的是,当用户单击pause pause按钮时会暂停/挂起线程,而当用户单击resume pause按钮时,程序应该会继续运行。我如何才能做到这一点?

我正在考虑从我的主类发送信号;但是,我不确定如何在线程中处理它们。是否可以在线程中处理从主类发送的信号?目前,我让线程向主类发送信号,这可以很好地工作,但我不确定如何从主类发送线程,并在线程中接收它们。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-01-31 18:45:02

好的,所以我建议你做一个内部线程变量,在你循环的每一步中都会检查这个变量+ QWaitCondition来恢复循环。

  1. 创建暂停方法,你将打开“暂停字段”(bool?),别忘了在你自己的循环中同步
  2. 使用QWaitCondition (参见Qt文档)来暂停线程恢复方法,你将关闭“暂停字段”并唤醒QWaitCondition

类MyWorker:公共QThread { QMutex :同步同步;QWaitCondition pauseCond;bool pause;public: MyWorker(...):pause(false) {} void resume() { sync.lock();pause = false;sync.unlock();pauseCond.wakeAll();} void pause() { sync.lock();pause = true;sync.unlock();} protected: void run() { while(someCondition) //猜测这是你的循环{ sync.lock();if(pause) pauseCond.wait(&sync);//在这个地方,你的线程将停止执行,直到有人调用resume sync.unlock();//执行您的操作};

票数 15
EN

Stack Overflow用户

发布于 2013-04-09 02:44:37

为了挂起一个工作线程,我使用了以下方法。

这是我的GUI.h文件的一部分:

代码语言:javascript
复制
public:
    QAtomicInt check;   //it has to be public to be reachable from a
                        //working thread; we’ll use it as a pause flag
private:
    int receiver;       //internal flag
    QThread *thread;    //we will use thread, won’t we?
    Worker *worker;     //here is where all the work is done
signals:
    void begin();       //we will also need a signal

下面是我的GUI.cpp文件的一部分:

代码语言:javascript
复制
Widget::Widget(){
    receiver = 0;
    check = QAtomicInt(1);    //you may use any number, even 42
    pb = new QPushButton("Start");    //I used a button to start, 
                                    //suspend and resume a working thread
    connect(pb, SIGNAL(clicked()), this, SLOT(start()));
    thread = new QThread;    //who did not read Maya Posch’s blog?
    worker = new Worker(this);    //we need a pointer to this to reach
              //our check flag, remember?
    worker->moveToThread(thread);
    connect(this, SIGNAL(begin()), worker, SLOT(compute()));
    connect(worker, SIGNAL(over()), this, SLOT(ovr()));
    thread->start();
}

void Widget::start() {
    if ( receiver == 0 ) {    //just to remember where we are
        pb->setText("Stop");
        receiver = 1;
        emit begin();    //here we start our heavy job
    } else if ( receiver == 1 ) {    //here we pause it
        pb->setText("Start");
        receiver = 2;
        while ( !(check.testAndSetOrdered(2, 3))) {}

//this is where all the magic is done testAndSetOrdered 
//may fail so we repeat it until it succeeds

    } else {
        pb->setText("Stop");
        receiver = 1;
        while ( !(check.testAndSetOrdered(3, 1))) {}

//first we have to restore check to its normal value. 
//This time we can almost never fail, but just in case 
//I leave the while block here

        emit begin();    //here we resume our job
    }
}

这是我的worker.h文件:

代码语言:javascript
复制
class Worker : public QObject {    //do not ask why I did not inherit from QThread, 
                                   //just read Maya Posch
    Q_OBJECT
public:
    Worker(Widget*);
public slots:
    void compute();    //the only slot here that does it all
signals:
    void over();       //we have to inform the GUI thread that we are over
private:
    int limit, counter;    //it is important to declare counter
    Widget *parent;
};

下面是我的worker.cpp文件的一部分:

代码语言:javascript
复制
Worker::Worker(Widget* par) {
    parent = par;    //store a pointer to the GUI thread
    counter = 1;     //it is important to initialize counter HERE
    limit = 100000000;
}

void Worker::compute() {
    while ( counter < limit ) {
        if ( parent->check.testAndSetOrdered(1, 2) ) {  //THERE

//testAndSetOrdered may fail, if check was set to another value in the GUI thread.
//If this is the case, we return and DO NOTHING. Compared to techniques with wait() 
//and QMutex and QWaitCondition, this approach is easier on CPU.

            //do your calculations HERE
            counter += 1;
            parent->check.testAndSetOrdered(2, 1);    

//before the next iteration we have to restore
//check to 1, and we don’t care if we fail here

        } else {
            return;
        }
    }

//now we get ready for yet another round of calculations and inform the GUI 
//thread that we are over with this round.

    counter = 1;
    emit over();
}

基本思想是使用QAtomicInt的特殊功能。在工作线程中,我们检查check是否保持不变。如果它被改变了,我们返回,什么也不做。要更改它,我们必须与工作线程竞争从GUI线程进行检查的访问权限。这就是我们需要while块的原因。我们将while块放在简历部分,尽管在大多数情况下,它会在第一次尝试时成功。但我们正在处理多线程,还记得吗?

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9075837

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档