| Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date | |
| All threads index page 4 | |
I hope a thread can be suspended (resumed) by click a suspend (resume)
button.
Here is a connection:
connect(progressCtrl->suspendButton, SIGNAL(clicked()), thread,
SLOT(suspend()));
Here is the slot:
void MyThread::suspend()
{
susp_mutex.lock();
susp_flag=true;
susp_mutex.unlock();
}
, and here is the wait condition in the thread loop:
{
while(MyThread::susp_flag)
MyThread::susp_cond.wait(&MyThread::susp_mutex);
}
I hope the thread can be suspended, but instead, I get error:
"A mutex must be unlocked in the same thread that locked it"
What's wrong? Could you mind sharing with me your experience on
suspend/resume a thread?
Thanks in advance,
Lingfa
--
[ signature omitted ]
Lingfa Yang wrote: > I hope a thread can be suspended (resumed) by click a suspend (resume) > button. > > Here is a connection: > connect(progressCtrl->suspendButton, SIGNAL(clicked()), thread, > SLOT(suspend())); Try adding Qt::QueuedConnection as the 5th argument to connect(). That way, the suspend() function will execute in the thread, instead of in the GUI thread. --Dave -- [ signature omitted ]
> Try adding Qt::QueuedConnection as the 5th argument to connect(). That > way, the suspend() function will execute in the thread, instead of in > the GUI thread. Thank you for your reply. I did it, but I got the same error. Lingfa -- [ signature omitted ]
Lingfa Yang wrote:
> , and here is the wait condition in the thread loop:
> {
> while(MyThread::susp_flag)
> MyThread::susp_cond.wait(&MyThread::susp_mutex);
> }
>
> I hope the thread can be suspended, but instead, I get error:
> "A mutex must be unlocked in the same thread that locked it"
I suspect from the code that you are running the while
loop in a thread that is not MyThread and it is that
thread in which the condition variable unlocks the mutex,
which would lead to the message that you see.
Usually a thread will own its mutexes and cond. vars,
(ie. they will be private variables in a thread class)
and they should not be made available to other threads.
--
[ signature omitted ]
Stephen Collyer wrote:
> Lingfa Yang wrote:
>
>
>> , and here is the wait condition in the thread loop:
>> {
>> while(MyThread::susp_flag)
>> MyThread::susp_cond.wait(&MyThread::susp_mutex);
>> }
>>
>> I hope the thread can be suspended, but instead, I get error:
>> "A mutex must be unlocked in the same thread that locked it"
>>
>
> I suspect from the code that you are running the while
> loop in a thread that is not MyThread and it is that
> thread in which the condition variable unlocks the mutex,
> which would lead to the message that you see.
>
> Usually a thread will own its mutexes and cond. vars,
> (ie. they will be private variables in a thread class)
> and they should not be made available to other threads.
>
Stephen,
Thank you for your reply. I think you are right. I made changes to make
sure the mutex and condition are created in the same thread:
{
while(this->susp_flag)
this->pCondition->wait(this->pMutex);
}
Still, I got the same error.
More idea?
Lingfa
--
[ signature omitted ]
Lingfa Yang wrote:
> Stephen Collyer wrote:
>> Usually a thread will own its mutexes and cond. vars,
>> (ie. they will be private variables in a thread class)
>> and they should not be made available to other threads.
Ignore this. It's nonsense as stated.
> Thank you for your reply. I think you are right. I made changes to make
> sure the mutex and condition are created in the same thread:
> {
> while(this->susp_flag)
> this->pCondition->wait(this->pMutex);
> }
>
> Still, I got the same error.
Can you put up more of the code ? It's not at
all clear how the whole thing fits together -
show the thread creation, and the classes you've
written and it'll be clearer as to what's going on.
--
[ signature omitted ]
> Can you put up more of the code ? It's not at
> all clear how the whole thing fits together -
> show the thread creation, and the classes you've
> written and it'll be clearer as to what's going on.
>
Thank you. Here come the whole impl.
1) "MyThread.h"
#include <QThread>
class PackageCore;
class MyThread : public QThread
{
Q_OBJECT
public slots:
void suspend();
void resume();
public:
MyThread(PackageCore *core);
virtual ~MyThread();
void run();
protected:
PackageCore *core;
};
2) "MyThread.cpp"
#include "MyThread.h"
#include "PackageCore.h"
#include <QMutex>
#include <QWaitCondition>
MyThread::MyThread(PackageCore *core)
: core(core)
{}
MyThread::~MyThread(){}
void MyThread::run()
{
core->setStop(false);
core->threadRun(); // heavy duty, time-costed, return back in
minutes or hours or days...
}
void MyThread::suspend()
{
core->pMutex->lock();
core->susp_flag=true;
core->pMutex->unlock();
}
void MyThread::resume()
{
core->pMutex->lock();
core->susp_flag=false;
core->pMutex->unlock();
core->pCondition->wakeOne();
}
3) The core:
void PackageCore::threadRun()
{
pMutex = new QMutex;
pCondition = new QWaitCondition;
switch(m_threadFunc)
{
case 0: // Plain text
extractPlainText();
break;
case 1: // tagged XML
extractXml();
break;
case 2: // unzipAll
ok = unzipAll();
break;
//...
}
delete pMutex; pMutex = NULL;
delete pCondition; pCondition = NULL;
}
4) The loop in subclass:
void OoXmlCore::extractText(const QString &partName, QTextStream &os)
{
emit setProgressLabel(tr("Working on \"%1\"...").arg(partName));
// ...
emit setRange(0, N);
for(int i=0; i<N; ++i)
{
if(m_stop) break;
emit progressValue(i); // To drive progress bar
while(this->susp_flag)
this->pCondition->wait(this->pMutex);
//...
}
}
--
[ signature omitted ]
Lingfa,
if you whant just suspend one thread and don't need to synchronize many
of them code like below should be enough:
class RunningThread{
static QMutex suspend_mutex;
run(){
while(){
suspend_mutex.lock(); suspend_mutex.unlock();
}
}
suspend(){
suspend_mutex.trylock();
}
}
Lingfa Yang wrote:
>
>> Can you put up more of the code ? It's not at
>> all clear how the whole thing fits together -
>> show the thread creation, and the classes you've
>> written and it'll be clearer as to what's going on.
>>
> Thank you. Here come the whole impl.
> 1) "MyThread.h"
>
> #include <QThread>
> class PackageCore;
>
> class MyThread : public QThread {
> Q_OBJECT
> public slots:
> void suspend();
> void resume();
> public:
> MyThread(PackageCore *core);
> virtual ~MyThread();
>
> void run();
> protected:
> PackageCore *core;
> };
>
> 2) "MyThread.cpp"
> #include "MyThread.h"
> #include "PackageCore.h"
> #include <QMutex>
> #include <QWaitCondition>
>
> MyThread::MyThread(PackageCore *core)
> : core(core)
> {}
> MyThread::~MyThread(){}
>
> void MyThread::run()
> {
> core->setStop(false);
> core->threadRun(); // heavy duty, time-costed, return back in minutes
> or hours or days...
> }
>
> void MyThread::suspend()
> {
> core->pMutex->lock();
> core->susp_flag=true;
> core->pMutex->unlock();
> }
>
> void MyThread::resume()
> {
> core->pMutex->lock();
> core->susp_flag=false;
> core->pMutex->unlock();
> core->pCondition->wakeOne();
> }
>
> 3) The core:
> void PackageCore::threadRun()
> {
> pMutex = new QMutex;
> pCondition = new QWaitCondition;
> switch(m_threadFunc)
> {
> case 0: // Plain text
> extractPlainText();
> break;
> case 1: // tagged XML
> extractXml();
> break;
> case 2: // unzipAll
> ok = unzipAll();
> break;
> //...
> }
> delete pMutex; pMutex = NULL;
> delete pCondition; pCondition = NULL;
> }
>
> 4) The loop in subclass:
> void OoXmlCore::extractText(const QString &partName, QTextStream &os)
> {
> emit setProgressLabel(tr("Working on \"%1\"...").arg(partName));
> // ...
> emit setRange(0, N);
> for(int i=0; i<N; ++i)
> {
> if(m_stop) break;
> emit progressValue(i); // To drive progress bar
> while(this->susp_flag)
> this->pCondition->wait(this->pMutex);
> //...
> }
> }
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
>
--
[ signature omitted ]
and what about QWaitCondition ?
-----Message d'origine-----
De : Dmitry.Samersoff@xxxxxxx [mailto:Dmitry.Samersoff@xxxxxxx]De la
part de Dmitry Samersoff
Envoyà : mardi 29 janvier 2008 17:48
à : Lingfa Yang
Cc : qt-interest@xxxxxxxxxxxxx
Objet : Re: how to suspend/resume a thread?
Lingfa,
if you whant just suspend one thread and don't need to synchronize many
of them code like below should be enough:
class RunningThread{
static QMutex suspend_mutex;
run(){
while(){
suspend_mutex.lock(); suspend_mutex.unlock();
}
}
suspend(){
suspend_mutex.trylock();
}
}
Lingfa Yang wrote:
>
>> Can you put up more of the code ? It's not at
>> all clear how the whole thing fits together -
>> show the thread creation, and the classes you've
>> written and it'll be clearer as to what's going on.
>>
> Thank you. Here come the whole impl.
> 1) "MyThread.h"
>
> #include <QThread>
> class PackageCore;
>
> class MyThread : public QThread {
> Q_OBJECT
> public slots:
> void suspend();
> void resume();
> public:
> MyThread(PackageCore *core);
> virtual ~MyThread();
>
> void run();
> protected:
> PackageCore *core;
> };
>
> 2) "MyThread.cpp"
> #include "MyThread.h"
> #include "PackageCore.h"
> #include <QMutex>
> #include <QWaitCondition>
>
> MyThread::MyThread(PackageCore *core)
> : core(core)
> {}
> MyThread::~MyThread(){}
>
> void MyThread::run()
> {
> core->setStop(false);
> core->threadRun(); // heavy duty, time-costed, return back in minutes
> or hours or days...
> }
>
> void MyThread::suspend()
> {
> core->pMutex->lock();
> core->susp_flag=true;
> core->pMutex->unlock();
> }
>
> void MyThread::resume()
> {
> core->pMutex->lock();
> core->susp_flag=false;
> core->pMutex->unlock();
> core->pCondition->wakeOne();
> }
>
> 3) The core:
> void PackageCore::threadRun()
> {
> pMutex = new QMutex;
> pCondition = new QWaitCondition;
> switch(m_threadFunc)
> {
> case 0: // Plain text
> extractPlainText();
> break;
> case 1: // tagged XML
> extractXml();
> break;
> case 2: // unzipAll
> ok = unzipAll();
> break;
> //...
> }
> delete pMutex; pMutex = NULL;
> delete pCondition; pCondition = NULL;
> }
>
> 4) The loop in subclass:
> void OoXmlCore::extractText(const QString &partName, QTextStream &os)
> {
> emit setProgressLabel(tr("Working on \"%1\"...").arg(partName));
> // ...
> emit setRange(0, N);
> for(int i=0; i<N; ++i)
> {
> if(m_stop) break;
> emit progressValue(i); // To drive progress bar
> while(this->susp_flag)
> this->pCondition->wait(this->pMutex);
> //...
> }
> }
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
>
--
[ signature omitted ]
Dmitry Samersoff wrote:
> Lingfa,
>
> if you whant just suspend one thread and don't need to synchronize
> many of them code like below should be enough:
>
> class RunningThread{
>
> static QMutex suspend_mutex;
>
> run(){
> while(){
> suspend_mutex.lock(); suspend_mutex.unlock();
> }
> }
>
> suspend(){
> suspend_mutex.trylock();
> }
>
> }
Dmitry,
Cool! The simpler the better. I will try.
Thanks,
Lingfa
--
[ signature omitted ]
Lingfa Yang wrote: >> >> static QMutex suspend_mutex; > > Cool! The simpler the better. I will try. Good luck! Please, don't miss *static* keyword above. Condition variables designed to wakeup couple of threads at once. If you have to start/stop the only thread - you don't need it. -- [ signature omitted ]
Lingfa Yang wrote: >I hope a thread can be suspended (resumed) by click a suspend (resume) >button. A thread is suspended if it's not doing anything. The call to QThread::exec() starts an event loop that waits for events and sleeps otherwise. If you want to block event reception, you'll need to go into a function that sleeps on a semaphore (acquire) until another thread allows it to continue (release). -- [ signature omitted ]
Attachment:
signature.asc
Description: This is a digitally signed message part.
As my understading, wait() is for synchronizing terminations of threads.
I have ever used sleep(timeout)
while(susp_flag)
{
Sleep(TIMEOUT);
}
This make the thread hand over cpu priority to other thread for TIMEOUT
secs.
Then, it will wake up and recheck susp_flag after TIMEOUT secs.
wait() without timeout value usually made hang up condition for me.
Or.. I recommend to terminate the thread with storing the current
data by clicking a suspend button, and to restart the thread with recall
the stored data by clicking a resume button.
-----Original Message-----
From: Lingfa Yang [mailto:lingfa@xxxxxxxxxxxx]
Sent: Tuesday, January 29, 2008 10:03 AM
To: Qt Interest
Subject: how to suspend/resume a thread?
I hope a thread can be suspended (resumed) by click a suspend (resume)
button.
Here is a connection:
connect(progressCtrl->suspendButton, SIGNAL(clicked()), thread,
SLOT(suspend()));
Here is the slot:
void MyThread::suspend()
{
susp_mutex.lock();
susp_flag=true;
susp_mutex.unlock();
}
, and here is the wait condition in the thread loop:
{
while(MyThread::susp_flag)
MyThread::susp_cond.wait(&MyThread::susp_mutex);
}
I hope the thread can be suspended, but instead, I get error:
"A mutex must be unlocked in the same thread that locked it"
What's wrong? Could you mind sharing with me your experience on
suspend/resume a thread?
Thanks in advance,
Lingfa
--
[ signature omitted ]