我最近开始学习QThreads,我有一个程序,它在一个单独的线程中运行一个4小时长的循环(这样我就可以继续使用图形用户界面)。我想要的是,当用户单击pause pause按钮时会暂停/挂起线程,而当用户单击resume pause按钮时,程序应该会继续运行。我如何才能做到这一点?
我正在考虑从我的主类发送信号;但是,我不确定如何在线程中处理它们。是否可以在线程中处理从主类发送的信号?目前,我让线程向主类发送信号,这可以很好地工作,但我不确定如何从主类发送线程,并在线程中接收它们。
发布于 2012-01-31 18:45:02
好的,所以我建议你做一个内部线程变量,在你循环的每一步中都会检查这个变量+ QWaitCondition来恢复循环。
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();//执行您的操作};
发布于 2013-04-09 02:44:37
为了挂起一个工作线程,我使用了以下方法。
这是我的GUI.h文件的一部分:
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文件的一部分:
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文件:
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文件的一部分:
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块放在简历部分,尽管在大多数情况下,它会在第一次尝试时成功。但我们正在处理多线程,还记得吗?
https://stackoverflow.com/questions/9075837
复制相似问题