Windows Azure Cloud Storage ermöglicht es Ihnen bereits ab 0,10€ pro GB/Monat die Vorteile der Cloud zu nutzen.
Hypercell ein ] Hypercell aus ] Zeige Navigation ] Verstecke Navigation ]
c++.de  
   
Advanced Developers Conference     
Bücher-Shop mit Amazon (Buchkategorien)C++ : Referenzen zu C++ : C++ Builder : Visual C++ : C# : Java : Spieleprogrammierung : Systemprogrammierung Linux : Software-Entwicklung : .NET : Compilertechnik : Algorithmen & Datenstrukturen : Objektorientierung : Entwurfsmuster : UML : eXtreme Programming : Scrum : Projektmanagement : Software-Testing : Datenbanken : Tom DeMarco : Dilbert : User Friendly
C/C++ Forum :: MFC (Visual C++) ::  CProgressCtrl reagiert nicht     Zeige alle Beiträge auf einer Seite Auf Beitrag antworten
Autor Nachricht
Jörg2010
Unregistrierter




Beitrag Jörg2010 Unregistrierter 08:46:25 09.02.2010   Titel:   CProgressCtrl reagiert nicht            Zitieren

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:

C/C++ Code:
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
void CDlgProgressDlg::OnBnClickedButton1()
{
    this->m_ProgressBar.ModifyStyle(0, PBS_MARQUEE);
    this->m_ProgressBar.SetMarquee(TRUE, 17);

    // Arbeit verrichten
    DoWork();

    EndDialog(IDOK);
}
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
void CDlgProgressDlg::OnBnClickedButton1()
{
this->m_ProgressBar.ModifyStyle(0, PBS_MARQUEE);
this->m_ProgressBar.SetMarquee(TRUE, 17);

// Arbeit verrichten
DoWork();

EndDialog(IDOK);
}
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
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
Martin Richter
Moderator

Benutzerprofil
Anmeldungsdatum: 18.04.2006
Beiträge: 13128
Beitrag Martin Richter Moderator 09:12:53 09.02.2010   Titel:              Zitieren

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 (MVP für C++) WWJD http://blog.m-ri.de
"A well-written program is its own heaven; a poorly written program is its own hell!" The Tao of Programming
Jörg2010
Unregistrierter




Beitrag Jörg2010 Unregistrierter 12:01:21 09.02.2010   Titel:              Zitieren

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
Martin Richter
Moderator

Benutzerprofil
Anmeldungsdatum: 18.04.2006
Beiträge: 13128
Beitrag Martin Richter Moderator 12:18:01 09.02.2010   Titel:              Zitieren

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 (MVP für C++) WWJD http://blog.m-ri.de
"A well-written program is its own heaven; a poorly written program is its own hell!" The Tao of Programming
Jörg2010
Unregistrierter




Beitrag Jörg2010 Unregistrierter 12:45:55 09.02.2010   Titel:              Zitieren

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
C/C++ Code:
AfxBeginThread(DoWork, this);
C/C++ Code:
AfxBeginThread(DoWork, this);
C/C++ Code:
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
Martin Richter
Moderator

Benutzerprofil
Anmeldungsdatum: 18.04.2006
Beiträge: 13128
Beitrag Martin Richter Moderator 13:08:44 09.02.2010   Titel:              Zitieren

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...

_________________
Martin Richter (MVP für C++) WWJD http://blog.m-ri.de
"A well-written program is its own heaven; a poorly written program is its own hell!" The Tao of Programming
Jörg2010
Unregistrierter




Beitrag Jörg2010 Unregistrierter 12:35:39 11.02.2010   Titel:              Zitieren

Danke für Hilfe, Martin.

Nun sind allerdings noch zwei weitere Fragen aufgetaucht. Und zwar Exceptions und MessageBoxes bei Threads.

Folgende Klasse als Beispiel
C/C++ Code:
1
2
3
4
5
6
7
8
1
2
3
4
5
6
7
8
// Header
class DialogSample : public CDialog
{
    static UINT __cdecl ThreadProc(LPVOID pParam);
    void DoWork();
    bool AssureData();
    void DisplayStatus();
};
C/C++ Code:
1
2
3
4
5
6
7
8
// Header
class DialogSample : public CDialog
{
static UINT __cdecl ThreadProc(LPVOID pParam);
void DoWork();
bool AssureData();
void DisplayStatus();
};
C/C++ Code:
1
2
3
4
5
6
7
8
// Header
class DialogSample : public CDialog
{
    static UINT __cdecl ThreadProc(LPVOID pParam);
    void DoWork();
    bool AssureData();
    void DisplayStatus();
};


C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 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"));
}
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 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"));
}
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 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
Martin Richter
Moderator

Benutzerprofil
Anmeldungsdatum: 18.04.2006
Beiträge: 13128
Beitrag Martin Richter Moderator 12:42:48 11.02.2010   Titel:              Zitieren

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 (MVP für C++) WWJD http://blog.m-ri.de
"A well-written program is its own heaven; a poorly written program is its own hell!" The Tao of Programming
Jörg2010
Unregistrierter




Beitrag Jörg2010 Unregistrierter 12:48:09 11.02.2010   Titel:              Zitieren

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
Martin Richter
Moderator

Benutzerprofil
Anmeldungsdatum: 18.04.2006
Beiträge: 13128
Beitrag Martin Richter Moderator 13:54:10 11.02.2010   Titel:              Zitieren

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.

_________________
Martin Richter (MVP für C++) WWJD http://blog.m-ri.de
"A well-written program is its own heaven; a poorly written program is its own hell!" The Tao of Programming
C/C++ Forum :: MFC (Visual C++) ::  CProgressCtrl reagiert nicht   Auf Beitrag antworten

Zeige alle Beiträge auf einer Seite




Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Sie können Beiträge in dieses Forum schreiben.
Sie können auf Beiträge in diesem Forum antworten.
Sie können Ihre Beiträge in diesem Forum nicht bearbeiten.
Sie können Ihre Beiträge in diesem Forum nicht löschen.
Sie können an Umfragen in diesem Forum nicht mitmachen.

Powered by phpBB © 2001, 2002 phpBB Group :: FI Theme

c++.de ist Teilnehmer des Partnerprogramms von Amazon Europe S.à.r.l. und Partner des Werbeprogramms, das zur Bereitstellung eines Mediums für Websites konzipiert wurde, mittels dessen durch die Platzierung von Werbeanzeigen und Links zu amazon.de Werbekostenerstattung verdient werden kann.

Die Vervielfältigung der auf den Seiten www.c-plusplus.de, www.c-plusplus.info, www.c-sar.de, www.c-plusplus.net und www.baeckmann.de enthaltenen Informationen ohne eine schriftliche Genehmigung des Seitenbetreibers ist untersagt (vgl. §4 Urheberrechtsgesetz). Die Nutzung und Änderung der vorgestellten Strukturen und Verfahren in privaten und kommerziellen Softwareanwendungen ist ausdrücklich erlaubt, soweit keine Rechte Dritter verletzt werden. Der Seitenbetreiber übernimmt keine Gewähr für die Funktion einzelner Beiträge oder Programmfragmente, insbesondere übernimmt er keine Haftung für eventuelle aus dem Gebrauch entstehenden Folgeschäden.