2011-01-09 3 views
1

Ich habe eine App, die ich arbeite, die Verwendung von einem ISP abfragt (Download Quota). Ich habe versucht, dies über "new Thread (ThreaProc)" einzufädeln, aber das hat nicht funktioniert, jetzt versuche ich einen IAsyncResult-basierten Ansatz, der das gleiche tut ... Ich habe keine Ahnung, wie ich das korrigieren soll, bitte helfen?Label.Text = Struct.Value (Microsoft.VisualStudio.Debugger.Runtime.CrossThreadMessagingException)

Die need-to-know:

// Global 
public delegate void AsyncPollData(ref POLLDATA pData); 

// Class scope: 
private POLLDATA pData; 

private void UpdateUsage() 
{ 
    AsyncPollData PollDataProc = new AsyncPollData(frmMain.PollUsage); 
    IAsyncResult result = PollDataProc.BeginInvoke(ref pData, 
    new AsyncCallback(UpdateDone), PollDataProc); 
} 

public void UpdateDone(IAsyncResult ar) 
{ 
    AsyncPollData PollDataProc = (AsyncPollData)ar.AsyncState; 
    PollDataProc.EndInvoke(ref pData, ar); 
    // The Exception occurs here: 
    lblStatus.Text = pData.LastError; 
} 

public static void PollUsage(ref POLLDATA PData) 
{ 
    PData.LastError = "Some string"; 
    return; 
} 

Antwort

3
lblStatus.Invoke(delegate() { lblStatus.Text = pData.LastError; }); 

Aktualisierung Werte über Threads ist nicht sicher, so dass der Compiler Sie warnt. Bei Verwendung von Invoke() wird der übergebene Code im GUI-Thread aufgerufen, sodass Sie einen GUI-Wert im GUI-Thread aktualisieren, der sicher ist.

+0

Das ist richtig, aber Sie könnten ein wenig erklären. – Machinarius

0

[Weitere Hinweise: ich verwende .NET 3.0] Auch

, wenn ich das in beschriebene Verfahren verwenden 'Wie GUI von einem anderen Thread in C# zu aktualisieren?' andere Teile dieser Funktion (UpdateDone) schlagen fehl (auch Teile, die nichts mit Threading zu tun haben, schlagen fehl, weil auf bestimmte Teile der Klasse außerhalb des aktuellen Threads zugegriffen wurde).

Korrigieren Sie mich, wenn ich falsch liege, aber da EndInvoke aufgerufen wird, sollte der Thread beendet sein. Daher sollten keine "Race conditions" existieren; Alle Daten gehören wieder dem primären Thread und ich sollte frei sein, was ich mit den Daten machen will ...?

Es gibt mehrere Elemente in dieser Struktur, die ich in der Klasse verwende; Gibt es einen besseren Weg, dies zu tun? Wie würdest du es machen?

Grundlegende Einschränkungen:
* Eine einzelne Funktion führt die Datenabfrage durch, die Idee ist nicht, es UI-Interaktion zu blockieren.
* Daher muss diese Funktion Asynchrone sein
* Die Haupt-Form-Klasse (frmMain) muss (Async) der Fertigstellung der fraglichen Funktion benachrichtigt werden und seine GUI wie erforderlich aktualisieren.
* Und natürlich in erster Linie, dass durch die Funktion gewonnenen Daten an die Mitglieder des frmMain leicht zugänglich sein muss

(Gott, Gewindeschneiden mit C so viel einfacher war ++)

3

Sie könnten sich eine neue Klasse erstellen und erstellen Sie Erweiterungen wie folgt aus:

public static class ThreadSafeHelpers { 
     public static void SetText(this Label varLabel, string newText) { 
      if (varLabel.InvokeRequired) { 
       varLabel.BeginInvoke(new MethodInvoker(() => SetText(varLabel, newText))); 
      } else { 
       varLabel.Text = newText; 
      } 
     } 
} 

und dann verwenden u dies überall in Ihrem Code wie folgt aus:

lblStatus.SetText(pData.LastError); 

Sie können mehrere ähnliche Erweiterungen für andere Dinge wie CheckBox, RadioButtons in derselben Klasse erstellen. Auf diese Weise können Sie sich leicht merken und Erweiterungsmethoden verwenden.

Natürlich könnten Sie auch eine normale Methode wie folgt (Hinweis Mangel an this neben Label) erstellen:

public static class ThreadSafeHelpers { 
     public static void SetText(Label varLabel, string newText) { 
      if (varLabel.InvokeRequired) { 
       varLabel.BeginInvoke(new MethodInvoker(() => SetText(varLabel, newText))); 
      } else { 
       varLabel.Text = newText; 
      } 
     } 
} 

und den Code wie folgt verwenden:

ThreadSafeHelpers.SetText(varLabel, newText); 
0

Thema Schlaf-Methode kann Arbeit für Sie

   Thread.Sleep(100); 
       this.Invoke((MethodInvoker)delegate 
       { 

        txtChatBox.Text += msgReceived.strMessage + "\r\n"; 
       }); 
Verwandte Themen