Hi
Ich habe ein Fenster von einem Vorgänger übernommen, das eigentlich nur aus einem Label, einer ProgressBar und einem Button (zum Abbrechen) besteht. Dieses Fenter wird üblicherweise vor einer Schleife erzeugt (oder wenn es schon existiert nur der Label geändert) und innerhalb der Schleife, die durch das Fenster dem Benutzer verdeutlicht werden soll, wird jedesmal showinfo("",wert) aufgerufen, um die Ansicht zu aktualisieren.
Nun habe ich, um bei größeren Datenbankoperationen ebenso dieses Fenster nutzen zu können, die Option Wert=-1 hinzugefügt, um den Style auf Marquee zu setzen.
[highlight=vb.net]
Class frmProgress
...
Public Sub showinfo(ByVal s As String, ByVal proz As Double)
Dim neu As Boolean : neu = False
If s <> "" And s <> lblFortschritt.Text Then 'Bei Angabe des Textes in einer Schleife ist nicht jedesmal ein DoEvents nötig
lblFortschritt.Text = s
neu = True
End If
If proz = -1.0 Then
prgFortschritt.Style = ProgressBarStyle.Marquee
Else
Dim p As Integer : p = Fix(proz)
If p > 100 Then p = 100
If p <> prgFortschritt.Value Then
prgFortschritt.Value = p
neu = True
End If
If neu Then Application.DoEvents()
End If
End Sub
End Class
Sub Beispiel()
Dim Anzahl As Integer = irgendwasgroßes
Dim i As Integer
Dim f As New frmProgress()
f.showinfo("Schleife1", 0.0)
f.Show(Me)
For i = 1 To Anzahl
f.showinfo("", i * 100 / Anzahl)
If f.Abbruch Then Exit For
'Do Something
Next
f.showinfo("Operation2", -1.0)
'externer Funktionsaufruf/Datenbankoperation
f.Close()
Application.DoEvents
[/highlight]
Das Problem ist nun, dass ich einerseits eigentlich die DoEvents() vermeiden wollte, es aber andererseits notwendig ist, damit überhaupt gezeichnet wird (beim Marquee zeichnet er auch nur den Start, aber bewegen tut sich nichts), und auch, damit der Klick auf den Cancel-Button registriert wird. Es ist schon so eigentlich inakzeptabel, dass der Klick auf den Cancel-Button erst dann registriert wird, wenn der Fortschritt groß genug ist, wieder einmal den Balken zu verlängern, auf der anderen Seite, möchte ich aber auch nicht in jedem Schleifendurchlauf alle Events dieses Programms vollständig abarbeiten, sonst brennt mir irgendwann der Prozessor durch.
Gibt es eine Möglichkeit, auch ohne DoEvents die Applikation dazu zu bringen trotzdem zu zeichnen und auf den Abbrechen Button zu reagieren?
PerformStep gestaltet sich extrem umständlich, weil die frmProgress ja nicht weiß, wie groß der jeweilige Step ist. Bei einer Schleife mit nur 3 Durchläufen wäre der Step 33, bei einer Schleife über 2000 Datensätze müsste ich 20 mal abwarten, bevor ich den Step 1 ausführe, und vorher den Value um den Step verringert zu setzen, um bei PerformStep den korrekten Step auszuführen, führt dazu, dass ich das Unterschreiten des Value 0 abfangen muss. Gut, ich könnte mir den Step ausrechnen aus dem aktuellen Value der ProgressBar und dem zu dem er gesetzt werden soll, das hilft mir aber nicht beim Marquee, der scheint sich nur durch das explizite Ausführen der Events zu bewegen.
Aus anderen Beiträgen erlese ich, dass ein eigener Thread/BackgroundWorker empfohlen wird, da stelle ich es mir aber etwas schwierig vor einerseits die Kommunikation zu regeln (ich müsste da jedesmal per Invoke dem anderen Thread sagen, dass der Balken aktualisiert werden soll und die Abbrechen-Eigenschaft abfragen) und mit BackgroundWorkern kenne ich mich nicht aus, gibt es da einen guten Link, um da was nachzulesen? Außerdem wird das frmProgress an so vielen Stellen im Programm verwendet, dass ich nur sehr ungern die Schnittstelle ändern würde.
Vielleicht weiß ja jemand Rat
Gruß
Martin
Ich habe ein Fenster von einem Vorgänger übernommen, das eigentlich nur aus einem Label, einer ProgressBar und einem Button (zum Abbrechen) besteht. Dieses Fenter wird üblicherweise vor einer Schleife erzeugt (oder wenn es schon existiert nur der Label geändert) und innerhalb der Schleife, die durch das Fenster dem Benutzer verdeutlicht werden soll, wird jedesmal showinfo("",wert) aufgerufen, um die Ansicht zu aktualisieren.
Nun habe ich, um bei größeren Datenbankoperationen ebenso dieses Fenster nutzen zu können, die Option Wert=-1 hinzugefügt, um den Style auf Marquee zu setzen.
[highlight=vb.net]
Class frmProgress
...
Public Sub showinfo(ByVal s As String, ByVal proz As Double)
Dim neu As Boolean : neu = False
If s <> "" And s <> lblFortschritt.Text Then 'Bei Angabe des Textes in einer Schleife ist nicht jedesmal ein DoEvents nötig
lblFortschritt.Text = s
neu = True
End If
If proz = -1.0 Then
prgFortschritt.Style = ProgressBarStyle.Marquee
Else
Dim p As Integer : p = Fix(proz)
If p > 100 Then p = 100
If p <> prgFortschritt.Value Then
prgFortschritt.Value = p
neu = True
End If
If neu Then Application.DoEvents()
End If
End Sub
End Class
Sub Beispiel()
Dim Anzahl As Integer = irgendwasgroßes
Dim i As Integer
Dim f As New frmProgress()
f.showinfo("Schleife1", 0.0)
f.Show(Me)
For i = 1 To Anzahl
f.showinfo("", i * 100 / Anzahl)
If f.Abbruch Then Exit For
'Do Something
Next
f.showinfo("Operation2", -1.0)
'externer Funktionsaufruf/Datenbankoperation
f.Close()
Application.DoEvents
[/highlight]
Das Problem ist nun, dass ich einerseits eigentlich die DoEvents() vermeiden wollte, es aber andererseits notwendig ist, damit überhaupt gezeichnet wird (beim Marquee zeichnet er auch nur den Start, aber bewegen tut sich nichts), und auch, damit der Klick auf den Cancel-Button registriert wird. Es ist schon so eigentlich inakzeptabel, dass der Klick auf den Cancel-Button erst dann registriert wird, wenn der Fortschritt groß genug ist, wieder einmal den Balken zu verlängern, auf der anderen Seite, möchte ich aber auch nicht in jedem Schleifendurchlauf alle Events dieses Programms vollständig abarbeiten, sonst brennt mir irgendwann der Prozessor durch.
Gibt es eine Möglichkeit, auch ohne DoEvents die Applikation dazu zu bringen trotzdem zu zeichnen und auf den Abbrechen Button zu reagieren?
PerformStep gestaltet sich extrem umständlich, weil die frmProgress ja nicht weiß, wie groß der jeweilige Step ist. Bei einer Schleife mit nur 3 Durchläufen wäre der Step 33, bei einer Schleife über 2000 Datensätze müsste ich 20 mal abwarten, bevor ich den Step 1 ausführe, und vorher den Value um den Step verringert zu setzen, um bei PerformStep den korrekten Step auszuführen, führt dazu, dass ich das Unterschreiten des Value 0 abfangen muss. Gut, ich könnte mir den Step ausrechnen aus dem aktuellen Value der ProgressBar und dem zu dem er gesetzt werden soll, das hilft mir aber nicht beim Marquee, der scheint sich nur durch das explizite Ausführen der Events zu bewegen.
Aus anderen Beiträgen erlese ich, dass ein eigener Thread/BackgroundWorker empfohlen wird, da stelle ich es mir aber etwas schwierig vor einerseits die Kommunikation zu regeln (ich müsste da jedesmal per Invoke dem anderen Thread sagen, dass der Balken aktualisiert werden soll und die Abbrechen-Eigenschaft abfragen) und mit BackgroundWorkern kenne ich mich nicht aus, gibt es da einen guten Link, um da was nachzulesen? Außerdem wird das frmProgress an so vielen Stellen im Programm verwendet, dass ich nur sehr ungern die Schnittstelle ändern würde.
Vielleicht weiß ja jemand Rat
Gruß
Martin
Comment