我有一个GUI线程,我可以在其中调用另一个MyQThread
write(QString text)
方法。
MyQthread
包含QMutex mutex
和QList<QString> list
。以下是write()
和run()
MyQThread
的方法:
void MyQThread::write(QString text)
{
mutex.lock();
list.append(text); //Point C
mutex.unlock();
start(); //Point D
}
void MyQThread::run()
{
mutex.lock();
while(!list.isEmpty())
{
QString text = list.takeFirst();
mutex.unlock();
...//do something
mutex.lock(); //Point A
}
mutex.unlock(); //Point B
}
例如,我们处于"A点"。在此之后,我们正在检查列表,它是空的,所以我们要去"B点"。此时调用write()
,互斥锁仍处于锁定状态,因此 GUI 线程在"C 点"之前等待。
现在我们处于"B点",在此GUI线程解锁并调用start((("D点"(之后。
是否有可能在"D点"MyQThread仍在运行?
在这种情况下,调用start()
什么都不做。并且list
中新添加的项目将不会在run()
中处理,直到下次调用write()
。
其他信息。就我而言,这里只是MyQThread的一个实例。
是的。尽管出现竞争条件的可能性很低,但我相信QThread仍然有可能发送信号等。在你打电话之前使用QThread::wait来确定start()
。
编辑:同意需要考虑QMutexLocker。该代码很快就会变得非常复杂,您无法确定您会记得在每个退出点解锁。
编辑2:也许QReadWriteLock在您的情况下可能更有趣?
@alexisdm感谢您的想法。这个解决方案怎么样:
class MyQThread:
public: QThread
{
...
QList<QString> list;
QMutex mutex;
QWaitCondition listNotEmpty;
}
void MyQThread::write(QString text)
{
QMutexLocker locker(&mutex);
list.append(text);
listNotEmpty.wakeAll();
}
void MyQThread::run()
{
forever
{
mutex.lock();
if(list.isEmpty())
listNotEmpty.wait(&mutex);
if(list.isEmpty())
{
mutex.unlock();
continue;
}
QString text = list.takeFirst();
mutex.unlock();
...//do something
}
}
那么wait()
的第二个参数呢 - unsigned long time = ULONG_MAX
.
在我看来,当长时间不调用该方法并且wait()
会在ULONG_MAX
后以run()
false
时,write()
似乎不会出错。在这种情况下,我只需要再次等待...
并在文档中写道:
互斥锁将返回到相同的锁定状态。
这是否意味着,即使互斥锁在wait()
或wait()
返回 false 之前未被锁定,wait()
后也会始终锁定互斥锁?
QThread 有 'isRunning' 和 'isDone' 的方法。因此,您可以查询线程状态。当然,您的线程可能仍在"D点"运行。
但你真的应该停在这里做一些阅读。https://www.qt.io/blog/2010/06/17/youre-doing-it-wrong和http://woboq.com/blog/qthread-you-were-not-doing-so-wrong.html
最肯定的是关于QMutexLocker的Qt文档。