Entwickler-Ecke
WPF / Silverlight - lange berechnung anzeige von Statusbar, Fenster eingefroren
new.Matrix - Di 17.06.08 14:38
Titel: lange berechnung anzeige von Statusbar, Fenster eingefroren
Hallo Zusammen,
Ich habe nun meine Software fertig entwickelt und sie läuft auch einwandfrei. Nun möchte ich noch einige Schönheistmakel beseitigen. Darunter habe ich auch folgendes Problem:
Meine Software besteht aus einer Auswertung, die einige Zeit in Anspruch nimmt, da viele Artikel ausgewertet werden müssen. Dabei habe ich einen Progressbar, welcher den aktuellen Status anzeigt. Bis jetzt habe ich dabei auf eine Zwischenlösung zurückgegriffen, da ansonsten das Fenster bis zum Schluss der Auswertung nicht neu gezeichnet wurde und zwar mithilfe diese codes:
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: 26: 27:
| private static System.Windows.Threading.DispatcherOperationCallback exitFrameCallback = new System.Windows.Threading.DispatcherOperationCallback(ExitFrame);
private static Object ExitFrame(Object state) { System.Windows.Threading.DispatcherFrame frame = state as System.Windows.Threading.DispatcherFrame;
frame.Continue = false; return null; }
public static void DoEvents() { System.Windows.Threading.DispatcherFrame nestedFrame = new System.Windows.Threading.DispatcherFrame();
System.Windows.Threading.DispatcherOperation exitOperation = System.Windows.Threading.Dispatcher.CurrentDispatcher.BeginInvoke( System.Windows.Threading.DispatcherPriority.Background, exitFrameCallback, nestedFrame);
System.Windows.Threading.Dispatcher.PushFrame(nestedFrame);
if (exitOperation.Status != System.Windows.Threading.DispatcherOperationStatus.Completed) { exitOperation.Abort(); } } |
Nun ist es zum Einten keine schöne Lösung und zum Anderen wirkt das Programm wie eingefroren, bis der nächste Artikel ausgewertet wird, denn dann wird erst das Fenster neu gezeichnet. Wie kann ich es lösen, dass jederzeit das Fenster angeklickt werden kann und dieses auch erscheint mit Statusanzeige?
Ich habe nun schon viel gelesen, nin aber noch ein Newbee und blicke langsam nicht mehr durch ob ich jetz backgroundworker oder Threading anwenden muss und wie ich am besten vorgehe...
Kann mir jemand helfen?
Kha - Di 17.06.08 20:30
Titel: Re: lange berechnung anzeige von Statusbar, Fenster eingefro
new.Matrix hat folgendes geschrieben: |
Ich habe nun schon viel gelesen, nin aber noch ein Newbee und blicke langsam nicht mehr durch ob ich jetz backgroundworker oder Threading anwenden muss und wie ich am besten vorgehe... |
Wenn du die Berechnung so in kleine Teile aufbrechen kannst, dass der User von einem Teil nichts merkt, nimmst du die "Dispatcher-Schleife", ansonsten Threads. Eine ausführliche Beschreibung zu beidem findest du unter "Threading Model [WPF]".
PS: Von DispatcherFrame höre ich heute zum ersten Mal :shock: .
PPS: Macht dir das eigentlich Spaß, jedes Mal den vollen Namespace zu tippen ;) ?
new.Matrix - Do 19.06.08 08:32
Erstmals danke für die Antwort!
...meinst du Threading Model [WPF] in der SDK Doku?
Ich habe esch schon mit Threading versucht, bin aber daran gescheiter. Ich hatte die Berechnung in eine Methode ausgelagert und diese in der Schleife in einem Thread gestartet. Nur lief mir da die Schleife durch und die Berechnung hat es glaube ich nur einmal gemacht, aber ich werde mich mal weiterdurchlesen...
Zitat: |
PPS: Macht dir das eigentlich Spaß, jedes Mal den vollen Namespace zu tippen ;) ? |
Nee dieser Code hatte ich selbst von irgendwo aufgeschnappt, ich selbst bevorzuge using ;-)
Christian S. - Do 19.06.08 11:07
Ich weiß gerade nicht, ob C# schon Sprachelemente hat, die das Arbeiten mit Threads erleichtern. In Oxygene geht es so:
Delphi-Prism-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| var max := 1000; progressBar1.Maximum := max; async begin for i : Integer := 0 to max do begin Thread.Sleep(100); Dispatcher.Invoke(DispatcherPriority.Normal, method; begin progressBar1.Value := i; end); end; end; |
Falls C# kein Äquivalent zum async-Statement hat, dann pack einfach alles von "async begin" bis zum letzten "end" in eine eigene Methode, die Du in einem eigenen Thread aufrufst. Der Rest sollte bis auf Syntax-Unterschiede genauso gehen.
new.Matrix - Do 19.06.08 13:29
Danke euch beiden! Habs nun mit der Hilfe zu Threading Modell der SDK Doku hinbekommen und zwar so:
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: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39:
| public class Haupklasse{ public delegate void DoCalculateDelegate(); public delegate void UpdateDisplayDelegate();
public Haupklasse() { InitializeComponent(); }
private void btnDoSomething_Click(object sender, RoutedEventArgs e) { ... DoCalculateDelegate fetcher = new DoCalculateDelegate(this.DoCalculate);
fetcher.BeginInvoke(null, null); }
public void DoCalculate() { for(i=0;i<anzahlberechnungen;i++) {
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,new UpdateDisplayDelegate(UpdateUserInterface)); } }
private void UpdateUserInterface() { } } |
Und das ists auch schon :-D einfach wenn man weiss wie...
Christian S. - Do 19.06.08 14:19
C# kann auch IIRC auch anonyme Methode und Delegates, die Du bei Dispatcher.Invoke aufrufen kannst. Dann brauchst Du keine eigene Methode im Code definieren.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!