1

スレッド「A」とスレッド「B」の2つのスレッドがあります。「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

すべてがうまく機能しているようです、それはただ1つのことです!〜IPCMessageEventが予想よりも早く呼び出されることがあるようです...

QCoreApplication::postEvent(gpApp, pEvent);

<---- pEvent is already destroyed here ---->

QMutex mutex; 
       mutex.lock();

だから私recvCondition.wait(&mutex, IPC_MESSAGE_WAIT_TIMEOUT);はロックされてタイムアウトになります。

この種の同期を行う他の方法はありますか?または、誰かがこの問題を修正/克服する方法について何か提案がありますか?

4

2 に答える 2

1

さて、あなたは古典的な競合状態を持っています。スレッドAは、イベントを投稿した直後に中断される可能性があり、スレッドBはイベントを処理して破棄します。条件変数の通知は、誰かがすでに待機している場合にのみ効果があるため、通知を見逃し、ブロックを無限に見逃します。

したがって、イベントを投稿する前にミューテックスをロックする必要があります。ただし、これには、イベントを処理するときにスレッドBこのミューテックスをロックする必要があります。そうしないと、スレッドBには何も待つ理由がないため(またはスレッドAが条件変数を待機する準備ができるまで「待機」する必要があることを知るため)、競合状態を防ぐことはできません。

別:

2つのスレッド(または2つのスレッドに存在するオブジェクト)間で信号/スロット接続を使用する場合は、を使用できますQt::BlockingQueuedConnection。これにより、スレッドAは信号を送信した後、スレッドBのイベントループが信号を処理するまでブロックします。

于 2012-06-29T10:15:03.317 に答える
1

Johannesに感謝します。私は、シグナル/スロットで提案された代替案を実際に試して使用する必要があります。

今のところ、スレッド「A」とスレッド「B」の間で使用されるQMutexとブールフラグを作成しました。

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;
};

多分それは最良の解決策ではありませんが、今のところはうまくいきます;)

于 2012-06-29T13:05:23.107 に答える