Auf UI warten



  • Martin, kann man AfxPumpMessage eigentlich auch aus einem Arbeitsthread aufrufen oder muss der Aufruf immer aus dem Hauptthread erfolgen?



  • Ah.. OK , wieder etwas neues , leider noch nicht ganz "neues gelernt", da ich nicht ganz verstehe was es mit AfxMessagePump auf sich hat, kann keine richtige Doku finden.

    Was ich gefunden habe ist CWinThread::PumpMessage(), d.h. ich könnte z.b.

    theApp.PumpMessage();
    

    aufrufen um zu veranlassen dass die MessageQueue abgearbeitet wird ?

    Danke,
    gruß
    Marcus



  • Martin Richter schrieb:

    Wenn bitte schon ein Message Pump drin ist, dann nur mit AfxPumpMessage und nicht TranslateMessage/DispatchMessage!

    AfxPumpMessage ist mit ebenfalls neu.
    Ein UpdateWindow hat zwar fürs erste etwas gebracht, jedoch ist ein Fortschrittsanzeige mit PBS_MARQUEE-Stil an Board.

    Ich werde dann wohl den Weg über den Worker Thread gehen.


  • Mod

    1. AfxPumpMessage ist ein shortcut fur AfxGetApp()->PumpMessage() (grob), allerdings bezieht sich dies immer auf den aktuellen Thread. Es kann also auch das aktuelle CWinThread Objekt sein. Also genaugenommen ein Shortcur für AgxGetThread()->PumpMessage();
    2. @sri: Man kann keine Nachricten für andere Threads abholen. PumpMessage/GetMessage funktioniert nur auf die Threadlokale Message Queue. Das ist der Grund warum man die UI nicht auslagert sondern den Arbeitsprozess.
    Nachrichten für Fenster laufen in dem Thread auf, der sie erzeugt...
    HTH



  • Das ganze Vorhaben klappt immer noch nicht.
    Vorweg: Auf die Löschoperation habe ich keinen Einfluss, die wird über eine andere Klasse "von vorne bis hinten durchgeführt".

    Die "Marquee-"Progressbar bewegt sich kein Stück und der Thread/die Anwendung ist komplett blockiert während des Löschens.

    Der Code sieht in etwa wie folgt aus:

    void CDeletionDialog::OnBnClickedDeleteFile
    {
        CString szFilename;
        GetDlgItemText(IDC_FILENAME, szFilename);
    
        this->m_ProgressBar.ShowWindow(SW_SHOW);
        this->m_ProgressBar.SetMarquee(TRUE, 17);                
        UpdateWindow();
    
        CWinThread * pThread = AfxBeginThread(DeletionThreadProc, 0);
    
        WaitForSingleObject(pThread->m_hThread, INFINITE);
    
        AfxMessageBox(_T("Die Datei wurde erfolgreich gelöscht."));
    }
    

    Eigentlich blockiert doch WaitForSingleObject die Awendung nicht, oder?


  • Mod

    HaJo. schrieb:

    Eigentlich blockiert doch WaitForSingleObject die Awendung nicht, oder?

    Doch genau das tut sie!
    Du musst hier eine Message-Loop einbauen und diese beenden, wen der Thread fertig ist.
    Weiterhin slltest Du unbedingt die UI disablen um keine Effekte wegen Reentrancy zu bekommen.



  • Martin Richter schrieb:

    Doch genau das tut sie!
    Du musst hier eine Message-Loop einbauen und diese beenden, wen der Thread fertig ist.

    Wie würde denn die MessageLoop aussehen?

    while(AfxPumpMessage())
    {
        if (WaitForSingleObject(pThread->m_hThread, 10) == WAIT_OBJECT_0)
            // Thread ist fertig
    }
    

    Martin Richter schrieb:

    Weiterhin slltest Du unbedingt die UI disablen um keine Effekte wegen Reentrancy zu bekommen.

    Habe ich bereits gemacht. Allerdings jedes Control einzeln. Geht das auch einfacher?


  • Mod

    Einfach den Main Dialog disablen.

    Nicht einfach PumpMessage ausführen. Das würde das Ende des Threads nicht mitbekommen, wenn keine Nachricht mehr kommt.

    Also zuerst ein

    while (::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE))
       AfxPumpMessage();
    


  • HaJo. schrieb:

    Geht das auch einfacher?

    Das ganzen Fenster / Dialog disablen, damit ist auch keine Eingabe auf einzelene Elemente innerhalb mehr möglich.

    BTW : Mein Frage mit dem AfxPumpMessage hat sich mit Deinem bsp. Code geklärt 🙂 Mich wundert nur dass die MSDN zu VC6 nichts finde, aber naja..

    Gruß
    Marcus



  • Danke für die Hilfen, es klappt nun.


Anmelden zum Antworten