Update-GUI Verwendung der BackgroundWorker-Klasse
Ich habe lange gesucht und festgestellt, dass ein guter Weg, um im hintergrund durchführen, arbeiten und aktualisieren der GUI über hintergrund-Arbeiter. Allerdings, dies zu tun (dumme) kleine Aufgabe (zählen von 1 bis 10000), das es nicht aktualisieren Sie die label-Inhalte, sondern druckt die debug! (Dies ist nur ein spike-Lösung für ein anderes Projekt natürlich...)
Hier der code:
public partial class MainWindow : Window
{
BackgroundWorker bw = new BackgroundWorker();
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw.WorkerReportsProgress = true;
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.RunWorkerAsync();
}
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("DONE");
}
void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Content = "going here: "+e.ProgressPercentage;
Debug.WriteLine(e.ProgressPercentage);
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
for (int i=0; i < 10000; i++)
{
bw.ReportProgress((i*100)/10000);
}
}
}
InformationsquelleAutor Miguel Ribeiro | 2011-03-04
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den
ProgressChanged
- Ereignis wird ausgelöst, die auf dem UI-thread, nicht der thread. In Ihrem code, der thread ist fast nichts tun (nur Schleife von 0 bis 10000, und rufen SieReportProgress
), die meiste Arbeit ist getan auf dem UI-thread. Im Grunde, Sie senden zu viele Fortschritte Benachrichtigungen. Weil dieses, der UI-thread ist fast immer beschäftigt und hat keine Zeit zum Rendern der neue Inhalt des Etiketts.Darstellung in WPF wird nicht sofort durchgeführt, wenn Sie eine Eigenschaft ändern der Steuerung, es erfolgt auf einem separaten dispatcher Rahmen, der verarbeitet wird, wenn der dispatcher hat nichts eiliger zu tun, basierend auf der Priorität der Aufgabe. Die Priorität für die Wiedergabe verwendet wird, hat einen Wert von 7 (
DispatcherPriority.Render
); dieProgressChanged
Veranstaltung ist gemarshallt an den UI-thread mit einer Priorität von 9 (DispatcherPriority.Normal
), wie angegeben auf der MSDN-Website. Also dieProgressChanged
Meldungen haben immer eine höhere Priorität als das Rendern, und da kommen Sie immer, den dispatcher, der nie Zeit hat zum Prozess der rendering-Aufgaben.Wenn Sie nur eine Verringerung der Häufigkeit der Benachrichtigungen, die app sollte gut funktionieren (aktuell, Sie senden 100 Benachrichtigungen für jeden Prozentwert, welche nutzlos ist):
Thread.Sleep(10);
helfen.Beliving oder nicht, ich dachte eigentlich es zu sehen, bevor Sie Ihren Kommentar! Es macht durchaus Sinn, dass die UI friert bei so viel telefonieren...
Es ist natürlich einfacher zu binden, eine Eigenschaft und Updates, die von den worker-thread.
absolut, und dies ist die bevorzugte Art, Dinge zu tun, die in WPF
InformationsquelleAutor Thomas Levesque
InformationsquelleAutor Akash Kava
Versuchen zu ändern, das label mit womething wie diese:
Beachten Sie, dass ich bin nicht sicher, es wird funktionieren. Ich kann nicht jetzt testen. Wenn es nicht funktioniert, lassen Sie mich wissen, und ich werde löschen Sie die Antwort.
Wenn Sie benötigen, die eine kanonische Weg, genau das zu tun, was Sie wollen, schauen Sie auf der Hat Antwort in diesem post: Wie aktualisiere ich die GUI aus einem anderen thread?
Sie können das gleiche mit WPF Dispatcher.Invoke. Aber das ist sowieso irrelevant: das ProgressChanged-Ereignis ausgelöst wird, auf der UI-thread, also Berufen, ist nicht erforderlich.
InformationsquelleAutor Jonathan