Sprache: C#
Wenn man aus einem Background Thread mit der UI einer Windows Forms anwendung kommunizieren (Werte ändern) möchte, muss man dies mittels Invoke machen, nachfolgendes Snippet zeigt wie man sich schnell eine einfache Methode schreiben kann die selbst entscheidet ob ein Invoke von Nöten ist oder nicht.
/// <summary>
/// Diese Methode wird von einem Background Thread (nicht UI Thread) aufgerufen
/// </summary>
/// <param name="max">Maximale Anzahl der Durchläufe</param>
private void BackgroundThreadAction(int max)
{
if (max < 0)
{
InvokeIfRequired(this.textBoxStatus, (MethodInvoker)delegate()
{
this.textBoxStatus.Text = "max value must be greater than zero";
});
return;
}
for (int i = 0; i < max; i++)
{
InvokeIfRequired(this.textBoxStatus, (MethodInvoker)delegate()
{
this.textBoxStatus.Text = String.Format("Processing value {0}", i);
});
Thread.Sleep(10);
}
}
/// <summary>
/// Methode die die UI Interaktionen durchführt.
/// </summary>
/// <param name="target">Control welches geändert wird, werden mehrere Controls geändert muss hier das Parent Control übergeben werden</param>
/// <param name="methodToInvoke">der Delegate der ausgeführt werden soll (UI Aktionen)</param>
private void InvokeIfRequired( Control target,Delegate methodToInvoke)
{
/* Mit Hilfe von InvokeRequired wird geprüft ob der Aufruf direkt an die UI gehen kann oder
* ob ein Invokeing hier von Nöten ist
*/
if (target.InvokeRequired)
{
// Das Control muss per Invoke geändert werden, weil der aufruf aus einem Backgroundthread kommt
target.Invoke(methodToInvoke);
}
else
{
// Die Änderung an der UI kann direkt aufgerufen werden.
methodToInvoke.DynamicInvoke();
}
}
/// <summary>
/// Diese Methode wird von einem Background Thread (nicht UI Thread) aufgerufen
/// </summary>
/// <param name="max">Maximale Anzahl der Durchläufe</param>
private void BackgroundThreadAction(int max)
{
if (max < 0)
{
InvokeIfRequired(this.textBoxStatus, (MethodInvoker)delegate()
{
this.textBoxStatus.Text = "max value must be greater than zero";
});
return;
}
for (int i = 0; i < max; i++)
{
InvokeIfRequired(this.textBoxStatus, (MethodInvoker)delegate()
{
this.textBoxStatus.Text = String.Format("Processing value {0}", i);
});
Thread.Sleep(10);
}
}
/// <summary>
/// Methode die die UI Interaktionen durchführt.
/// </summary>
/// <param name="target">Control welches geändert wird, werden mehrere Controls geändert muss hier das Parent Control übergeben werden</param>
/// <param name="methodToInvoke">der Delegate der ausgeführt werden soll (UI Aktionen)</param>
private void InvokeIfRequired( Control target,Delegate methodToInvoke)
{
/* Mit Hilfe von InvokeRequired wird geprüft ob der Aufruf direkt an die UI gehen kann oder
* ob ein Invokeing hier von Nöten ist
*/
if (target.InvokeRequired)
{
// Das Control muss per Invoke geändert werden, weil der aufruf aus einem Backgroundthread kommt
target.Invoke(methodToInvoke);
}
else
{
// Die Änderung an der UI kann direkt aufgerufen werden.
methodToInvoke.DynamicInvoke();
}
}
Alte URL:
/snippet/threadsichere-gui-aenderungen/1043
Siehe hierzu auch
http://dotnet-snippets.de/dns/threadsicheres-zuweisen-von-control-eigenschaften-SID829.aspx
Ich hab mir das Snippet gerade mal angesehen, ich finde allerdings dass dieser Weg der ’schönere‘ ist weil man so direkt mehrere Aktionen in dem anonymen Delegaten machen kann und nicht immer nur eine Property setzen kann 🙂
Siehe auch
„Asynchrones nachladen von Bildern in DataGridView“ hier bei .Net-Snippet.de
🙂
Hallo,
kann mir jemand bitte mal das „Parent Control“ erklären? Bei Google finde ich nichts gescheites bzw. ich kann damit nichts anfangen und bräuchte es aber dringend…
Danke schonmal!
P.S. Sehr gutes Snippet 😀