c++ 11 async with MFC



  • Hallo

    Versuche gerade mit std::async eine Funktion asynchron zu starten die unter anderem eine Funktion aufruft um auf der gui zu loggen. Sprich eine Listbox füllt.

    Doch sobald ich einen Zugriff auf die Listbox mache hängt die Applikation

    vereinfacht:

    std::async([&](){ loglistbox_.AddString("Hallo Welt"); UpdateData();});
    

    Wie bekomme ich denn das ganze asynchron hin ohne dass die GUI blockiert wird?



  • Du kannst, generell gesprochen, GUI Updates nur im GUI Thread machen. Wenn du versuchst es aus nem anderen Thread zu machen, wird eines aus der folgenden Liste passieren:

    1. Es geht, meistens, aber hin und wieder gibt es Probleme.
    2. Es geht überhaupt nicht (Exception/Fehlercode).
    3. Das Programm hängt sich weg (Deadlock).
    4. Es geht indem der Aufruf an den GUI Thread weiter geleitet wird. Wenn der GUI Thread in dem Moment aber gerade keine Messages dispatcht, sondern z.B. darauf wartet dass der andere Thread fertig wird, dann hast du wieder Fall (3).

    Einfache Möglichkeit: Neue Log-Messages in eine (synchronisierte) Queue stellen, und dem GUI Thread dann ne Nachricht posten dass es neue Log-Messages gibt.



  • Wenn es um MFC geht verweise ich ja so gerne auf Flounder/Mr. Newcomer. Er zeigt dir wie es geht. Nicht nur in diesem Beitrag, du kannst auch sonst sehr viel von ihm lernen:
    http://www.flounder.com/asynchexplorer.htm



  • Wieso willst Du es überhaupt asynchron machen?
    Sind Deine Datenmengen wirklich so groß?



  • wie gesagt der Code ist nur vereinfacht.

    Ich verbinde mich in der Async Methode zu einem Sever das unter anderem etwas länge dauern kann. Dass loggen ist nur Nebenschauplatz.

    Wieso das ganze hängt liegt wohl daran dass ich den Rückgabewert nicht auswerte bzw abspeichere.

    result_ = std::async([&](){ loglistbox_.AddString("Hallo Welt"); UpdateData();});
    

    Speichere ich mir mein result als member habe ich kein deadlock mehr.
    Nichts desto trotz muss ich das loggen in die Listbox per Postmessage machen. Dann klappts.



  • Dürfte ich hierzu noch eine Frage stellen. In der async methode installiere ich zusätlich eine Callback die vom Server aufgerufen wird.

    Die Callback benötigt aber eine Messageloop was natürlich über den async Befehl nicht gegeben ist.

    Gibt es hier eine Lösung?



  • async<void> schrieb:

    Speichere ich mir mein result als member habe ich kein deadlock mehr.
    Nichts desto trotz muss ich das loggen in die Listbox per Postmessage machen. Dann klappts.

    Das ist resikant. Bist Du sicherm, dass der String auch bis zur Abarbeitung bestehen bleibt.
    Ich würde in jedem Fall eine Queue nehmen und dann liber in einem Timer die Queue im UI Thread abarbeiten.
    Solche Windows Nachrichten gehören einfach nicht in einen anderen Thread