| 

.NET C# Java Javascript Exception

1
Hallo zusammen,

ich habe innerhalb einer WindowsForm ein Codestück, das ich schon sehr oft verwendet habe, und das nun erstmals Probleme bereitet. Den Code werden die meisten kennen:

delegate void SetStatusTextCallback(string sText);
public void SetStatusText(string sText)
{
if (InvokeRequired)
{
SetStatusTextCallback d = new SetStatusTextCallback(SetStatusText);
Invoke(d, new object[] { sText }); // **** hier bleibt das Programm hängen
}
else
{
lbStatus.Text = sText;
}
}

Der Code funktioniert mehrmals ohne Probleme, so lange der Invoke nicht notwendig ist. Beim 4. Aufruf wird der Invoke dann notwendig, und die Methode bleibt in der markierten Zeile hängen. Wenn ich einen Breakpoint an den Anfang der Methode setze, sehe ich, dass beim Invoke die Methode SetStatusText nicht aufgerufen wird.
Wenn ich Invoke und InvokeRequired auf lbStatus aufrufe, passiert das gleiche.
Hat jemand eine Idee, was da passiert?
05.07.2011
KN 1,7k 1 8
KN 1,7k 1 8
2 Antworten
1
Könnte es ein Deadlock sein? Etwa so: der UI-Thread wartet auf einen Background-Thread, dieser ruft SetStatusText, läuft in den InvokeRequired-Zweig, der kommt aber nicht weiter, weil der UI-Thread ja noch blockiert ist...

Probier mal BeginInvoke statt Invoke.
05.07.2011
Matthias Hlawatsch 13,2k 4 9
Genau das wars. Danke!
KN 05.07.2011
Bitteschön - freut mich zu lesen :-)
Matthias Hlawatsch 05.07.2011
0
Hallo,

Auf welcher Ebene befindet sich eigentlich Deine Methode? Wenn Du das so in den Code der Form eingebaut hast wird this angenommen. Du möchtest aber eine Textbox aktualisieren, also musst Du der Methode das Element mitgeben. Etwa so

delegate void SetStatusTextCallback(TextBox itm, String sText);

protected virtual void SetStatusText(TextBox itm, String sText)
{
if (itm.InvokeRequired)
{
SetStatusTextCallback d = new SetStatusTextCallback(SetStatusText);
itm.Invoke(d, new object[] { itm, sText });
}
else
{
lbStatus.Text = sText;
}
}
06.07.2011
LutzJ 1,3k 1 8
Sowohl this.InvokeRequired (this = Form), als auch itm.InvokeRequired gehen auf den gleichen UI-Thread, das sollte also egal sein.
Man kann es auch so machen wie du schreibst, insbesondere, wenn man bei verschiedenen Textboxen den Text updaten will, ist das praktischer. Man kann auch allgemein das Control übergeben (System.Windows.Forms.Control), dann kann man bei verschiedenen Controls (Textboxen, Labels etc) das Text-Attribut ändern. Man könnte sogar den Attributnamen (Hier: "Text") als string übergeben und dann per Reflection nicht nur den Text, sondern ein beliebiges Attribut ändern.
KN 06.07.2011
Da hast Du natürlich Recht. Allerdings hat dieses Konstrukt bei mir bisher immer wie erwartet funktioniert. Aber Du hast das jetzt ja mit BeginInvoke hinbekommen....
LutzJ 06.07.2011
Bei mir hatte der angegebene Code bisher ja auch immer funktioniert. Und ich hatte es in meinem Code auch schon mit dem Aufruf von Invoke und InvokeRequired auf dem Control versucht, und es hatte nicht funktioniert, eben weil ich ein Deadlock hatte. Es war einfach ein anderes Problem.
Deine Methode ist aber sicherer, falls Micosoft irgendwann seine Architektur ändert.
KN 06.07.2011

Stelle deine .net-Frage jetzt!
TOP TECHNOLOGIES CONSULTING GmbH