| 

.NET C# Java Javascript Exception

5
Hallo,
wie kann ich während eine Suche ausgeführt wird, meine Oberfläche aktualisieren, damit irgendwie ersichtlich ist, das gerade eine Suche ausgeführt wird?

Habe mich bereits mit Threads beschäftigt, diese können aber nicht auf UI Elemente eines anderen Threads zugreifen.

Hat jemand Vorschläge wie ich das umsetzen kann?
News:
31.08.2011
mrmee 745 1 8
4 Antworten
2
Hallo, ich habe sowas vor kurzem gemacht.

Am einfachsten ist es, wenn du dir mal die Klasse BackgroundWorker anschaust.

Beispiel:
public partial class Form1 : Form
{
private BackgroundWorker _worker;

public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
_worker = new BackgroundWorker { WorkerReportsProgress = true, WorkerSupportsCancellation = true };
_worker.DoWork += searchOperation;
_worker.ProgressChanged += worker_ProgressChanged;
_worker.RunWorkerAsync();
}

void searchOperation(object sender, DoWorkEventArgs e)
{
// Deine suche hier
var i = 1 + 1;

// Nach jedem Suchfortschritt progress melden
_worker.ReportProgress(1);
}

void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar.performStep();
}


}


Wichtig ist das in deiner Suchoperation das _worker.ReportProgress() aufgerufen wird. Du kannst mit der Methode entweder ein prozentualen Wert mit geben den du dann in der worker_ProgressChanged Methode mit e.ProgressPercentage abrufen kannst, oder aber du kannst die ReportProgress Methode mit 2 Parametern aufrufen:

_worker.ReportProgress(1, 50);
_worker.ReportProgress(2, "Suche beendet");

void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (e.ProgressPercentage == 1)
{
progressBar.Value = (int)e.UserState;
}
else if (e.ProgressPercentage == 2)
{
labelStatus.Text = (string)e.UserState;
}
}


Hierbei eignet sich der erste Parameter auch besonders gut für ein Enum. Hoffe geholfen zu haben und wünsche viel Erfolg.

Grüße
31.08.2011
Nicolai Schönberg 2,4k 2 9
Verstehe ich das richtig? Sobald ich dann "searchOperation" aufrufe, wird diese in einem anderen Thread ausgeführt?
mrmee 01.09.2011
2
Nein, nicht wenn Du die Methode "searchOperation" aufrufst. Die Abarbeitung der "searchOperation" durch einen anderen Thread wird mit der Zeile
_worker.RunWorkerAsync();
gestartet. Der _worker wurde so eingestellt, dass sein "DoWork" effektiv die "searchOperation" ist, siehe
_worker.DoWork += searchOperation;
ffordermaier 01.09.2011
Alles klar. Danke
mrmee 01.09.2011
3
Mit dem Stichwort "Threads" bist Du schon auf der richtigen Spur. "UI Elemente eines anderen Threads" ist aber eine etwas verquere Formulierung: es gibt einfach nur einen Thread, der das UI manipulieren darf. Folglich solltest Du Deine Suche in einem anderen Thread laufen lassen. Wenn sie fertig ist, kannst Du aus dem Suchthread mit Dispatcher.Invoke wieder zurück in den UI-Thread, um das Ergebnis anzuzeigen.

Den Hintergrundthread kannst Du z.B. über einen BackgroundWorker starten. Ein Beispiel samt Hintergundinfo findest Du in diesem Artikel aus dem MSDN-Magazin.
31.08.2011
Matthias Hlawatsch 13,2k 4 9
Sowas hatte ich mir schon fast gedacht. Allerdings wollte ich das vermeiden, weil damit ein zimlicher Haufen an Arbeit auf mich zukommt. Tja, wenn ich schon am Anfang daran gedacht hätte :(
mrmee 31.08.2011
1
Am einfachsten geht das vermutlich, wenn Du zur Akualisierung der Oberfläche den SynchronizationContext nutzt. Der Context sorgt dafür, dass die Anfrage wieder im UI thread ausgeführt wird.
SynchronizationContext.Current.Post(
new SendOrPostCallback(
ignore => meinControl.Refresh()), null);


In Silverlight wird eher dazu geraten den Dispatcher zu nutzen:
Deployment.Current.Dispatcher.BeginInvoke(
() => meinControl.Refresh);
31.08.2011
1
Wenn Du Anpassungen an Deinem Code vermeiden möchtest, könntest Du auch eine Art Splashscreen anzeigen während die Suche ausgeführt wird, und diesen Splashscreen in einem eigenen Thread laufen lassen.
Beispiel gibt es hier.
31.08.2011
sgf 426 3
Das ist ein Windows-Forms-Beispiel. mrmee hatte nach WPF gefragt.
Matthias Hlawatsch 31.08.2011
1
Erstens steht wpf nicht im Text (sondern darunter, was ich zugegebenermassen übersehen habe), zweitens läuft der Splashscreen auch in wpf-Anwendungen, und drittens ist es eine kleine Fingerübung von keinen fünf Minuten, ihn auf wpf umzubauen. Das interessante an dem Beispiel ist das Prinzip, dass das Programm im UI-Thread arbeitet, während der Splashscreen in einem eigenen Thread läuft und aktualisiert werden kann, d.h. das Programm ist eigentlich single-threaded, erscheint dem Anwender aber nicht-blockierend.
sgf 31.08.2011
Danke für deinen Hinweis und das Beispiel. Das klappt und reicht für meine Anwendung (derzeit).
mrmee 01.09.2011

Stelle deine .net-Frage jetzt!