我有两个线程,让我们说线程“A”和线程“B”。 将“A”帖子的自定义QEvent线程化为线程“B”,然后它应该等到线程“B”处理此事件。
到目前为止我做了什么:
我的活动课程:
class IPCMessageEvent : public QEvent
{
public:
IPCMessageEvent(QWaitCondition* pConditions) : QEvent(IPC_MESSAGE_RECEIVED)
, mpWaitCondition(pConditions)
{ };
~IPCMessageEvent()
{
mpWaitCondition->wakeOne();
};
private:
QWaitCondition* mpWaitCondition;
};
我的主题“A”:
QWaitCondition recvCondition;
IPCMessageEvent* pEvent = new IPCMessageEvent(&recvCondition);
QCoreApplication::postEvent(gpApp, pEvent);
QMutex mutex;
mutex.lock();
recvCondition.wait(&mutex, IPC_MESSAGE_WAIT_TIMEOUT);
我的主题“B”:处理收到的事件并将其销毁。调用 ~IPCMessageEvent 析构函数,因此将为线程“A”中的wakeOne()
启动recvCondition
。
一切似乎都很好,这只是一件事! 看起来有时 ~IPCMessageEvent 会在预期之后被调用...
QCoreApplication::postEvent(gpApp, pEvent);
<---- pEvent is already destroyed here ---->
QMutex mutex;
mutex.lock();
因此我的recvCondition.wait(&mutex, IPC_MESSAGE_WAIT_TIMEOUT);
将被锁定并将达到超时时间。
还有其他方法可以进行这种同步吗? 或者也许有人有任何建议如何解决/克服这个问题?
答案 0 :(得分:1)
嗯,你有一个经典的竞争条件。发布事件后,您的线程A可能会被中断,线程B会处理并销毁它。由于条件变量的通知仅在某人已经在等待时才有效,因此您会错过通知,从而无限地阻止您的阻止。
因此,您需要在发布事件之前锁定互斥锁。但是,这要求您的线程B 也在处理事件时需要锁定此互斥锁。否则,您无法阻止竞争条件,因为线程B没有理由等待任何事情(或者知道它应该“等待”,直到线程A准备好等待条件变量)。
<强>替代:强>
如果在两个线程(或两个线程中的对象)之间使用信号/插槽连接,则可以使用Qt::BlockingQueuedConnection
。这确保线程A在发出信号之后阻塞,直到线程B中的事件循环处理它。
答案 1 :(得分:1)
谢谢约翰内斯, 我真的需要尝试使用你建议的替代信号/插槽。
我现在做的是: 我创建了一个QMutex和boolean标志,用于线程“A”和线程“B”之间。
bool mIsProcessingMessage;
QMutex mIsProcessingMessageLock;
在主题“A”中,我发布了这样的事件:
IPCMessageEvent* pEvent = new IPCMessageEvent();
{ // Inform everyone that we will be processing our message.
QMutexLocker locker(&mIsProcessingMessageLock);
mIsProcessingMessage = true;
};
QCoreApplication::postEvent(gpApp, pEvent, Qt::HighEventPriority);
forever // Loop until event will get processed.
{
QMutexLocker locker(&mIsProcessingMessageLock);
if (mIsProcessingMessage == false)
break;
::Sleep(2); // Don't load up the CPU.
};
在处理我的事件时,在线程“B”中我只是将“mIsProcessingMessage”标志设置为true,如下所示:
{
QMutexLocker locker(&mIsProcessingMessageLock);
mIsProcessingMessage = false;
};
也许这不是最好的解决方案,但它现在有效;)