Problem: Hintergrundthread läuft nicht solange im Mainwnd keine MessageBox offen ist



  • moin

    hab da nen problem, da das nun schon im 2. programm auftritt und ich es net beheben kann muss ich hier mal fragen:

    also ich hab mein mainprogramm (docview)
    in diesem hab ich diverse thread laufen nun hab ich einen thread augemacht der nachrichten in ein anderen dialog rein schreibt (statusmeldungen) diese statusmeldungen schreibt der thread aber nur in den dialog, wenn im mainwindow eine afxmessagebox offen ist. solange diese offen ist funktioniert alles super.

    wenn ich die afxmessagebox aber schliesse läuft mein thread nicht weiter...
    (da ich im mainwindow aber auf die abarbeitung des threads warten muss, hängt sich dieses halt auch weg)

    meine frage: wieso muss ich ne messagebox aufmachen damit mein programm weiter läuft?

    leider ist das schwer nachzubilden (codeschnipsel)

    hat da jemand ne idee?

    mfg LT



  • Ganz einfach.

    Der Dialog der beschrieben wird gehört deinem Main-Thread.
    Der "Dialog-Schreibe" Thread ruft nun SetDlgItemText() oder sowas auf, was intern zu einem SendMessage() wird.
    Damit SendMessage() aber funktioniert, muss der "Besitzer-Thread" des Fensters/Dialogs Messages pumpen. Also der Main-Thread.
    So lange eine MessageBox offen ist, werden Messages gepumpt.
    =>
    So lange eine MessageBox offen ist, geht es.

    Offenbar hast du keinen Message-Loop ausserhalb der MessageBox in deinem Main-Thread, und daher geht es dort nicht.



  • hmmm ok klingt logisch 😉 so und wie erzeuge ich einen messageloop in dem mainthread?


  • Mod

    Indem Du CWinThread::Run aufrufst...
    Oder zyklisch AfxPumpMessage ausführst...



  • moin martin,

    hmmm versteh ich net ...
    ich will ja nu das meine messages immer abgerufen werden...
    also nehm ich an ich muss das in nen thread oder so packen ...

    nu sagste ruf das auf ... hmmm nur einmal oder doch in nem thread ?

    ich hab da im forum sowas gefunden:

    MSG msg;
    PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
    CoInitializeEx(NULL, COINIT_MULTITHREADED);
    
    BOOL bRet = FALSE;
    while ((bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
    {
    
        if(msg.message == WM_MYMESSAGE){
        //Starte timer
        SetTimer(NULL,TIMERID, 100,MyTimerProc);
        }else  {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    

    so wenn ich das ganze in nen thread packe und den thread beim programmstart starte geht das dann ???

    thx LT


  • Mod

    Wenn Du die MFC verwendest und einen Workerthread mit der MFC gebaut hast, nach doku, musst Du nur dafür sorgen, das InitInstance mit TRUE verlassen wird. CWinThread::Run macht den Rest.

    Was willst Du nun. Pures WinAPI oder MFC. Hier mpostest Du im MFC Forum und bekommst entsprechende Antworten...



  • du ich will das es geht ...

    hier schreibt jeder was anderes ...

    also ich hab nen thread

    UINT WolkeDruckerJob(LPVOID pParam){
    do{
    setAnzeigeText("meintext der angezeigt werden soll");
    ....
    }while(irgendwas);
    }
    

    so starte ich den thread

    AfxBeginThread(WolkeDruckerJob, this, THREAD_PRIORITY_NORMAL);
    

    die funktion setAnzeigeText ist in meiner main-klasse deklariert
    wenn ich nun nach dem starten app->Run(); sage wird wieder alles angezeigt aber der code nach run wird nicht mehr ausgeführt...

    und bitte schreib mal mehr als nen 2 zeiler als antwort ...



  • @LordTerra
    Das Problem ist dass du das Pferd vom Schwanz her aufgezäumt hast.

    LordTerra schrieb:

    wenn ich nun nach dem starten app->Run(); sage wird wieder alles angezeigt aber der code nach run wird nicht mehr ausgeführt...

    Genau das ist das Problem.

    Die Windows GUI Funktionen sind darauf ausgelegt, dass jeder Thread dem Fenster gehören (ein Fenster gehört dem Thread der es erzeugt hat) immer Messages pumpen tut.
    Üblicherweise gehören alle Fenster dem Main-Thread, und der tut nix ausser Messages pumpen, und halt auf diverse Messages reagieren (ein Button wurde geklickt => starte Vorgang X. etc.).

    Wenn du im Main-Thread etwas tun willst was länger dauert, hast du ein Problem.
    Die "Lösung" einen 2. Thread rauszustarten der die GUI aktualisiert während der Main-Thread beschäftigt ist, funktioniert aber nicht.

    Also mach es umgekehrt: der Main-Thread startet nen 2. Thread der die länger dauernde Aufgabe übernimmt ("Worker-Thread"). Danach macht der Main-Thread sofort weiter mit Messages pumpen (=der Message Handler muss "returnen").
    Und wenn der Worker-Thread fertig ist, soll er dem Main-Thread ne Message posten.

    Dabei kann es dann nötig sein ggf. diverse GUI Elemente (Buttons, ...) zu disablen während der Worker-Thread läuft, je Programm halt.


  • Mod

    Nachtrag: Run ist die MessagePump!!!

    Danach wird natürlich kein Code mehr ausgeführt bis eben die Messageloop terminiert.

    Ansonsten hast Du ja auch CWinThread::OnIdle, die regelemässig ausgeführt wird, wenn keine Nachricht anliegt.
    Ansonsten werde Dir klar was Du willst.

    Wenn Du schreibst: "ich wil das es geht", dann lerne es richtig zu machen und zu verstehen. Oder stelle Fragen die man auch beantworten kann.

    Lerne zu vestehen was SendMessage wirlich tut wenn die Fenster von unterschiedlichen Threads erzeugt wurden (steht alles in der MSDN).


Anmelden zum Antworten