CProgressCtrl reagiert nicht
-
Moin, moin!
Ich habe einen modalen Dialog, der auf Kopfdruck eine "Arbeit" verrichten soll. Dem Benutzer wird ein CProgressCtrl im Marquee-Stil angezeigt. Die "Arbeit" dauert zwischen 3 Sekunden und 1,5 Minuten. Leider ist der Dialog während dieser Zeit blockiert und die Marquee-ProgressBar (das laufende Fortschrittsband) wird nicht angezeigt. Der Code sieht so aus:
void CDlgProgressDlg::OnBnClickedButton1() { this->m_ProgressBar.ModifyStyle(0, PBS_MARQUEE); this->m_ProgressBar.SetMarquee(TRUE, 17); // Arbeit verrichten DoWork(); EndDialog(IDOK); }
Wenn ich DoWork auskommeniere (und EndDialog) wird die Progressbar korrekt dargestellt.
Grüsse
Jörg
-
Solche Controls können nur Arbeiten und was anzeigen, wenn auch eine Nachrichten Schleife läuft...
Lagere DoWork in einen eigenen Thread aus, Disable Deinen Dialog bis der Thread fertig ist. Führe dann erst EndDialog aus.
-
Martin Richter schrieb:
Solche Controls können nur Arbeiten und was anzeigen, wenn auch eine Nachrichten Schleife läuft...
Lagere DoWork in einen eigenen Thread aus, Disable Deinen Dialog bis der Thread fertig ist. Führe dann erst EndDialog aus.
Puh... das ist immer mit soviel Aufwand verbunden. Der Thread müsste auch auf Daten der Dialogklasse zurückgreifen etc.
Zudem weiß ich nicht so ganz genau wie ich dann den Arbeitsthread und den Dialog-Thread wieder korrekt synchronisiere...
P.S.: Visual Studio stellt hier zufällig eine pragma-Anweisung o.ä. bereit, um bestimmt Code-Teile in einen Thread auszulagern ohne das der Programmierer das tun muss?
Grüsse
Jörg
-
Auf die Daten des Dialoges zugreifen ist doch kein Problem. Höchstens auf Controls.
Übergib einfach einen Zeiger. Und so lange der Dialog wartet und nichts macht brauchst Du nicht mal eine Threadsynchronisation zum Schutz der Daten. Da Du die Funktion DoWork schon hast eignet die sich doch für eine Threadfunktion
-
Martin Richter schrieb:
Und so lange der Dialog wartet und nichts macht brauchst Du nicht mal eine Threadsynchronisation zum Schutz der Daten. Da Du die Funktion DoWork schon hast eignet die sich doch für eine Threadfunktion
Das verstehe ich nicht ganz. Wenn ich
AfxBeginThread(DoWork, this);
in OnBnClickedButton1 oder über DoWork aufrufen, wird der Thread doch gestartet
und gleich EndDialog aufgerufen, da der Thread parallel arbeitet.Oder verstehe ich hier etwas falsch?
Grüsse
Jörg
-
Deshalb habe ich doch geschrieben:
Warten bis der Thread fertig ist.Ich würde es so machen.
1. Dialog disablen. (Damit es keine erneute Bedienung des Dialoges gibt)
2. Thread starten. Prograssbar starten. Funktion verlassen.
3. Wenn Thread fertig PostMessage einer benutzerdefinierten Nachricht.
4. In dem Handler im Dialog für die benutzerdefinierte Nachricht EndDialog ausführen.Dann sorgt die Dialog Messagepunp für den Rest.
Wenn Du willst kannst Du auch zyklisch in DoWork mal nachrichten bearbeiten...
-
Danke für Hilfe, Martin.
Nun sind allerdings noch zwei weitere Fragen aufgetaucht. Und zwar Exceptions und MessageBoxes bei Threads.
Folgende Klasse als Beispiel
// Header class DialogSample : public CDialog { static UINT __cdecl ThreadProc(LPVOID pParam); void DoWork(); bool AssureData(); void DisplayStatus(); };
// Code-Datei UINT __cdecl DialogSample::ThreadProc(LPVOID pParam) { BOOL bSucceeded = FALSE; try { DialogSample * pDlg = reinterpret_cast<DialogSample *>(pParam); // (1) pDlg->DoWork(); // diese Methode kann Ausnahmen werfen // (2) if (!pDlg->AssureData()) throw Exception(); bSucceeded = TRUE; } catch(const Exception & e) {} PostMessage(pDlg->m_hWnd, WM_UM_THREAD_FINISHED, 0, static_cast<WPARAM>(bSucceeded)); // (3) pDlg->DisplayStatus(); return 0; } void DialogSample::DisplayStatus() { AfxMessageBox(_T("helo")); }
(1), (2)
Ist das so in Ordnung mit den Ausnahmen oder kann das Probleme geben?(3)
Kann ich aus dem Thread heraus eine MessageBox aufrufen oder ist das nicht sinnvoll?Grüsse
Jörg
-
Wenn Du die Ausnahmen behandelst ist das doch prima.
Ansonsen kann auch ein Thread eine MessageBox anzeigen.
Dir muss nur klar sein, dass dieses MessageBoxc eben in dem anderen Thread läuft
Dein Main Dialog sollte immer noch disabled sein!
-
Martin Richter schrieb:
Ansonsen kann auch ein Thread eine MessageBox anzeigen.
Dir muss nur klar sein, dass dieses MessageBoxc eben in dem anderen Thread läuft
Dein Main Dialog sollte immer noch disabled sein!Ok, das wollte ich wissen oder der WorkerThread hier auch GUI-Elemente "anzeigen" darf. Danke.
Grüsse
Jörg
-
Ein CWinThread hat eine komplette eigene MessagePump bei Bedarf (Run). Ich verwende unter bestimmten Umständen ganz eigene UI Threads...
Man muss sich nur klar sein was man macht!
Denn wenn der eine UI Thread sich meldet kann der andere ja auch noch was machen. Sprich Dir muss klar sein, dass Deine Software und manche Handler reentrant werden.