Toon posts:

VB.NET 2008 Progressbar probleem...

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Hi,
Ik heb een goed werkende code geschreven om het programma een tijdje te laten wachten. Deze wachttijd word weergeven via de Progressbar. Hier is nix mee. Als de loop eindigd dan is de pb.value gelijk aan de pb.max waarde. Echter, op het scherm is de progressbar nog (lang) niet zo ver.

Laat ik het programma verder lopen dan haalt de progressbar wel het einde, maar niet op het moment dat de waarde is ingegeven. Ofwel, de Progressbar is niet direct. Deze geeft niet direct waarde X weer, maar kruipt naar waarde X toe. Dit duurt ongeveer een seconde.

Is hier een oplossing voor?

OS: Vista
Visual Basic 2008 SP1

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Je main thread is (klaarblijkelijk) "te druk" met het verwerken van je taak waardoor de GUI geen tijd heeft om bij te werken; beiden worden namelijk, wat ik zo uit je topicstart opmaak althans, op de main thread uitgevoerd.

Wat je het best kunt doen is de taak in een backgroundworker gooien en die de progress laten reporten. Minder gecompliceerd (maar eigenlijk mag ik je dit niet aanraden) is om om de zoveel tijd (lees: iedere X-iteraties bijvoorbeeld) even de .Refresh() aan te roepen. Maar daarmee hou je jezelf alleen voor de gek; de progressbar zal dan wel 'beter' lopen, maar feitelijk blockt 'ie (en de rest van je GUI) nog steeds in de tussentijd.

Backgroundworker is dus the way to go (of zelf een eigen thread aan stampen en buiten de backgroundworker om gaan).

[ Voor 9% gewijzigd door RobIII op 28-01-2010 20:36 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • Sebazzz
  • Registratie: September 2006
  • Laatst online: 14:51

Sebazzz

3dp

En in het geval dat je wel een tweede thread gebruikt: Zorg ervoor dat je niet te vaak statusupdates naar je form geeft, dat kan averechts werken.

[Te koop: 3D printers] [Website] Agile tools: [Return: retrospectives] [Pokertime: planning poker]


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Normaal hertekend een progressbar zichzelf bij het zetten van de waarde. Voorbeeldcode (c#):
C#:
1
2
3
4
5
            for (int i = progressBar1.Minimum; i < progressBar1.Maximum; i++)
            {
                Thread.Sleep(1);
                progressBar1.Value += 1;
            }


Evengoed is een backgroundworker een goed idee. :) Wat ik me kan voorstellen is dat je nu een Backgroundworker hebt, maar te vaak de progressie-methode aanroept of een main-thread hebt die zelf te druk is met andere zaken. In de event-queue van de form ontstaat dan een wachtrij.

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Als deze code loopt, loopt er niets anders.
De aanroep is Countdown(3000,true)

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
34
    Private Sub Countdown(ByVal lMilliseconds As Long, ByVal bCountDownTrue As Boolean)

        ' Init
        Dim lMin As Long
        Dim lMax As Long
        Dim lCurrent As Long
        lMin = Microsoft.VisualBasic.DateAndTime.Timer * 1000
        lMax = lMin + lMilliseconds
        lCurrent = lMin

        ' Set busy
        bBusy = True

        ' set progress bar
        pbTime.Value = 0
        pbTime.Maximum = lMax - lMin
        pbTime.Minimum = 0

        ' focus to form so you don't have to click twice to press X
        Me.Focus()

        ' countdown
        While lCurrent < lMax
            pbTime.Value = lCurrent - lMin
            Label1.Text = lCurrent  - lMin
            lCurrent = Microsoft.VisualBasic.DateAndTime.Timer * 1000
            Application.DoEvents()
        End While
        pbTime.Value = pbTime.Maximum
        Application.DoEvents()

        ' Ready
        bBusy = False
    End Sub


Als ik de interface op Standaard zet van Vista, dan is het probleem verholpen. Ik zie dan de classic blauwe Progressbar in plaats van de groene.

Edit:
Als ik de code voor de countdown weg laat, en meteen naar pbTime.Value = pbTime.Maximum spring dan vult de progressbar zich in ongeveer 5 stappen over een tijd van ca. 1 seconde. Dit in plaats van in één keer vol weertegeven.

[ Voor 30% gewijzigd door Verwijderd op 28-01-2010 22:10 ]


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Hmm... Je hebt gelijk. :p Dit is eigenlijk gewoon een Windows-bug. Stukje testcode met mogelijke oplossing:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
        private void button1_Click(object sender, EventArgs e)
        {
            button1.Visible = false;
            var s = Stopwatch.StartNew();
            var max = 3000;
            progressBar1.Maximum = max;
            long current;
            while ((current = s.ElapsedMilliseconds) < max)
            {
                Thread.Sleep(1);
                progressBar1.Value = (int)current + 1; //hack to disable animation
                progressBar1.Value = (int)current;
            }
            progressBar1.Value = max;
            button1.Visible = true;
        }

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
pedorus schreef op donderdag 28 januari 2010 @ 22:07:
Hmm... Je hebt gelijk. :p Dit is eigenlijk gewoon een Windows-bug. Stukje testcode met mogelijke oplossing:
Je bent geweldig. _/-\o_ Dit lijkt te werken!

[ Voor 3% gewijzigd door Verwijderd op 28-01-2010 22:55 ]

Pagina: 1