Frage

Ich habe einen Thread, der COM-Objekte erstellt, die eine Single-Threaded-Wohnung benötigen.

Ursprünglich dieser Hauptfunktion des Threads steckte es in eine WaitForMultipleObjects Schleife. Offensichtlich ist dies ein Problem, weil es das COM-Nachrichtensystem verhindert, dass es des Job.

I ersetzt diese mit MsgWaitForMultipleObjects als Lösung, aber jetzt in eine Frage, die ich bin mit: MsgWaitForMultipleObjects manchmal (oft) kehrt WAIT_FAILED, aber stellt nicht einen Fehler.

Der Code behandelt ein WAIT_FAILED Rückgabewert von nur fort und versucht MsgWaitForMultipleObjects wieder anzurufen. Der Aufruf von MsgWaitForMultipleObjects zurückkehren ein paar Mal WAIT_FAILED (die ich gesehen habe, ist 9), aber dann funktioniert es plötzlich ohne Probleme.

Der Code ist so geschrieben, dass dies möglicherweise in eine Endlosschleife gehen könnte, wenn die Funktion WAIT_FAILED aus einem triftigen Grund zurückkehrten. Ich weiß, ich sollte dieses Problem zu beheben, aber im Moment bin ich in Anbetracht es eine Arbeit um ", weil die MsgWaitForMultipleObjects Anruf schließlich gelingen wird.

Dieser Code getestet wird unter Windows 7, Vista und XP (alle 32-Bit, Windows 7 32- und 64-Bit).

Hat jemand eine Idee, warum dies geschieht?

Der entsprechende Code:

bool run = true;
while (run)
{
    DWORD ret = MsgWaitForMultipleObjects(2, events, FALSE, INFINITE, 
        QS_ALLINPUT);

    switch (ret)
    {
        case WAIT_OBJECT_0:
        {
            ResetEvent(events[0]);
            ProcessWorkQueue();
            break;
        }

        case WAIT_OBJECT_0 + 1:
        {
            run = false;
            break;
        }

        case WAIT_OBJECT_0 + 2:
        {
            MSG msg;
            while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
                DispatchMessage(&msg);
            break;
        }

        case WAIT_FAILED:
        {
            Logger::Output(L"Wait failed in Notify::Run(), error is " 
                + boost::lexical_cast<std::wstring>(GetLastError()));
        }
    }
}

Beispiel Ausgabe wäre:

Wait failed in Notify::Run(), error is 0
Wait failed in Notify::Run(), error is 0
Wait failed in Notify::Run(), error is 0
Wait failed in Notify::Run(), error is 0
Wait failed in Notify::Run(), error is 0
Wait failed in Notify::Run(), error is 0
Wait failed in Notify::Run(), error is 0
Wait failed in Notify::Run(), error is 0
Wait failed in Notify::Run(), error is 0
// At this point, the wait succeeds

Ich glaube, der WAIT_FAILED Rückgabewert nur auftritt, nachdem die Wartezeit durch eine Nachricht aufgebrochen worden ist.

War es hilfreich?

Lösung

Das sollte nicht passieren, und ich kann sicher nicht genau erklären, Warum es tut. Ich mache ein paar Hinweise haben, aber.

Zuerst Sie anrufen nicht TranslateMessage() vor DispatchMessage() in Ihrer Nachricht Pumpe. Das ist schlimm juju, und Sie wollen nicht schlecht Juju irgendwo in der Nähe MsgWaitForMultipleObjects().

Sie können auch versuchen wollen MsgWaitForMultipleObjectsEx() explizit aufrufen, falls es nicht das gleiche Problem aufweisen:

DWORD ret = MsgWaitForMultipleObjectsEx(2, events, INFINITE, QS_ALLINPUT, 0);

Schließlich könnte es weit hergeholt, aber überlegen, was nach MsgWaitForMultipleObjects() zurückkehrt geschieht und vor GetLastError() genannt wird. Ohne Berücksichtigung der Zuordnung zu ret, sehe ich einen impliziten Aufruf von std::wstring Konstruktor.

Können Sie std::wstring Konstruktor nicht garantieren, einigen Nebeneffekt hat, dass der letzten Fehlercode des Threads löscht? Ich kann sicher nicht, so dass ich den Anruf zu GetLastError() in eine guten bewegen würde, altmodisch, Atom Zuordnung zu einer DWORD Variable in der ersten Zeile der case Aussage.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top