Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Affje

Treue Seele

  • »Affje« ist der Autor dieses Themas

Beiträge: 89

Beruf: Student

  • Private Nachricht senden

1

31.05.2011, 20:54

[C#] Ich verzweifle noch an der progressBar

Hallo,

ich bin wirklich kurz vor'm Verzweifeln. Ich habe in meinem Projekt eine progressBar, die natürlich,w er hätte es gedacht, den Fortschritt einer Aktion anzeigen soll. Ich klicke auf einen Button, danach wird dem .Max ein Wert zugewiesen und eine bool'sche Variable auf true gesetzt.
Wenn dieser Wert auf true ist, kann ich ich auf ein Bild klicken, dort werden dann Punkte gemalt und eben eine andere Variable hochgezählt, die dann auf der progressBar angezeigt werden soll. Das leidge Thema ist aber, dass die progressBar einfach viel zu spät akualisiert wird und das fast schon lächerlich aussieht, man klickt und drölf Sekunden später wird dann die blöde progressBar aktualisiert.

Hier mal der Code-Ausschnitt:

Quellcode

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
        //Klick auf Bild, Zeichnen-Funktion falls isActive == true
        private void Image_MouseClick(object sender, MouseEventArgs e)
        {
            int x = e.X, y = e.Y;

            if (isActive)
            {
                //Schuss dem Array hinzufügen
                shotsX[count] = x;
                shotsY[count] = y;
                rings[count] = Ring;
                count++;
                    
                Shots++;
                
                //progressBar per Invoke() ruckelfrei darstellen? - denkste wohl
                progressBarShots.Invoke((MethodInvoker)delegate
                {
                    progressBarShots.Value = Shots;
                    progressBarShots.Update();
                });
 
                labelShotsLeft.Text = Convert.ToString(MaxShots - Shots);

                Shot(x, y, diameter, diameter, farbe);

                if (MaxShots - Shots == 0)
                {
                    isActive = false;
                    buttonAdd.Enabled = true;
                }
            }
        }


Ich habe diesen Invoke-Workauround(?) in einem anderen Forum gefunden und wenn ich damit in einem neuen Projekt eine progressBar aktualisiere, klappt's wunderbar:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
        private void button1_Click(object sender, EventArgs e)
        {

            double i = 0;
            double limit = 65535;

            while (i < limit)
            {
                progressBar1.Invoke((MethodInvoker)delegate
                {
                    progressBar1.Value = (int)((i / limit) * 100 + 1);
                });

                i++;
            }
        }


Wie kriege ich denn jetzt das so hin, dass es wirklich instant beim Klick aktualisiert wird?
MfG

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

31.05.2011, 22:21

An Deiner Stelle würde ich diesen Code da (aus welchem Forum auch immer) lieber nicht verwenden. Der frisst unnötig Ressourcen, sprich CPU-Zeit, da er offensichtlich für einen parallelen Thread gedacht ist, aber dort auf voller Last läuft und immer wieder versucht in den Context des GUI-Threads umzuschalten. Meiner Meinung nach sehr unklug.

Dass in Deiner View trotzdem nichts passiert liegt schlicht daran, dass Du Die lange Operation in genau dem gleichen Thread ausführst (nämlich der synchronen Image_MouseClick-Methode), wie der Thread, der zum Zeichnen aktiv werden müsste. Er ist aber schon aktiv, nur leider eben in einem anderen Stück Code. Und ein einzelner Thread kann eben nicht an zwei Stellen gleichzeitig arbeiten.
Lagere die Operation des Maus-Klicks in einen Background-Worker aus, dann funktioniert auch alles wie üblich und das Invoke macht auch erst einen Sinn. Denn es gibt nichts zu invoken, wenn du ohnehin schon im Context des GUI-Threads unterwegs bist.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Wirago

Alter Hase

Beiträge: 1 193

Wohnort: Stockerau

Beruf: CRM Application Manager

  • Private Nachricht senden

3

01.06.2011, 07:22


BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

4

01.06.2011, 07:30

Ein Background-Worker ist für seinen Zweck aber besser geeignet, da er ja auch eine Fortschrittsmeldung verwenden will. Das kann er sich zwar mit einem Thread auch selber bauen, ein Background-Worker bringt das aber schon von Haus aus mit.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Affje

Treue Seele

  • »Affje« ist der Autor dieses Themas

Beiträge: 89

Beruf: Student

  • Private Nachricht senden

5

01.06.2011, 08:34

Danke schonmal für die Hilfe :)
Wie gehe ich jetzt im weiteren Verlauf mit dem backGroundWorker vor? Wenn ich also die Methode Image_Click "aktiviere", dann starte ich ja den Worker. Aber wie "verteile" ich dann die Arbeit?
Was muss z.b. ins DoWork? Kommt da dann die Image_Click Methode rein?

MfG

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

6

01.06.2011, 11:27

Wenn dieser Wert auf true ist, kann ich ich auf ein Bild klicken, dort werden dann Punkte gemalt und eben eine andere Variable hochgezählt, die dann auf der progressBar angezeigt werden soll.

Wann und wie soll denn hochgezählt werden? Immer wenn die Maus sich bewegt? Immer wenn ein Punkt gemalt wird? Ständig mit einer konstanten Geschwindigkeit?

Affje

Treue Seele

  • »Affje« ist der Autor dieses Themas

Beiträge: 89

Beruf: Student

  • Private Nachricht senden

7

01.06.2011, 12:08

Wenn dieser Wert auf true ist, kann ich ich auf ein Bild klicken, dort werden dann Punkte gemalt und eben eine andere Variable hochgezählt, die dann auf der progressBar angezeigt werden soll.

Wann und wie soll denn hochgezählt werden? Immer wenn die Maus sich bewegt? Immer wenn ein Punkt gemalt wird? Ständig mit einer konstanten Geschwindigkeit?
Hochgezählt wird dann, wenn auf das Bild geklickt wird.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

8

01.06.2011, 12:12

Dann versteh ich nicht wo dein Problem liegt. Da brauchst du weder Threads noch sonst irgendwas. Einfach im entsprechenden Click Event ProgressBar.Value inkrementieren!?

C#-Quelltext

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
        private void Image_MouseClick(object sender, MouseEventArgs e)
        {
            int x = e.X, y = e.Y;

            if (isActive)
            {
                shotsX[count] = x;
                shotsY[count] = y;
                rings[count] = Ring;
                count++;
                    
                Shots++;
                progressBarShots.Value = Shots;
 
                labelShotsLeft.Text = Convert.ToString(MaxShots - Shots);

                //Shot(x, y, diameter, diameter, farbe);

                if (MaxShots - Shots == 0)
                {
                    isActive = false;
                    buttonAdd.Enabled = true;
                }
            }
        }

Affje

Treue Seele

  • »Affje« ist der Autor dieses Themas

Beiträge: 89

Beruf: Student

  • Private Nachricht senden

9

01.06.2011, 12:45

Dann versteh ich nicht wo dein Problem liegt. Da brauchst du weder Threads noch sonst irgendwas. Einfach im entsprechenden Click Event ProgressBar.Value inkrementieren!?

C#-Quelltext

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
        private void Image_MouseClick(object sender, MouseEventArgs e)
        {
            int x = e.X, y = e.Y;

            if (isActive)
            {
                shotsX[count] = x;
                shotsY[count] = y;
                rings[count] = Ring;
                count++;
                    
                Shots++;
                progressBarShots.Value = Shots;
 
                labelShotsLeft.Text = Convert.ToString(MaxShots - Shots);

                //Shot(x, y, diameter, diameter, farbe);

                if (MaxShots - Shots == 0)
                {
                    isActive = false;
                    buttonAdd.Enabled = true;
                }
            }
        }
Mach ich doch.

Quellcode

1
2
               Shots++; 
                progressBarShots.Value = Shots;


Ich inkrementiere es halt indirekt über eine Variable, könnte natürlich auch progressBarShots.value++; machen, aber ist ja dasselbe.
Verzögerung von fast einer Sekunde, bis die bar aktualisiert und der richtige Wert angezeigt wird.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

10

01.06.2011, 12:48

Und wenn du mal den Aufruf dieser Methode Shot() auskommentierst so wie in meinem Beispiel oben hast du diese Verzögerung auch? Ich vermute nämlich fast mal dass du in der Methode irgendwas machst das dein Programm entsprechend lange lahmlegt...

Werbeanzeige