2009-03-03 4 views
1

Im folgenden Code MessageReceived ist auf einem anderen Thread zu label1 und wenn man versucht, darauf zuzugreifen werde ich diese Fehlermeldung erhalten:Hilfe für 'Cross-Thread-Betrieb Fehler' benötigt in C#

Cross-thread operation not valid: Control 'label1' accessed from a thread other than the thread it was created on.

foo.MessageReceived += new Agent.MessageReceivedHandler(foo_MessageReceived); 

void foo_MessageReceived(Message message) 
{ 
    label1.Text = message.Body; 
}  

Wie kann ich das lösen?

Mehr: anscheinend muss ich delegate und invoke verwenden, aber ich weiß nicht, wie, können Sie bitte näher erläutern?

+1

Exaktes Duplikat (nicht NPR, wie ich angeklickt fälschlicherweise): http://stackoverflow.com/questions/244591 http://stackoverflow.com/questions/142003 http://stackoverflow.com/questions/ 470390 unter anderem. –

Antwort

0

Make immer sicher, dass Sie Ihre GUI auf dem Hauptthread (GUI-Thread) aktualisieren.

foo.MessageReceived + = neuer Agent.MessageReceivedHandler (foo_MessageReceived);

public delegate void MyDelegate(Message msg); 
void foo_MessageReceived(Message message) 
{ 
    if (InvokeRequired) 
    { 
     BeginInvoke(new MyDelegate(foo_MessageReceived),new object[]{message}); 
    } 
    else 
    { 
     label1.Text = message.Body; 
    } 
} 
0

Das ist absolut nicht hilfreich. Ich wünschte, ich könnte mich selbst abstimmen.

Ich kann veraltet sein, aber von dem, was ich erinnere, Sie dürfen nichts in der GUI von etwas anderem als dem Hauptthread ändern.

1

Delegieren, Aktualisieren des Etiketts zu dem Thread, der das Etikett erstellt hat, anstatt zu versuchen, es direkt zu aktualisieren.

4

Hoffentlich wird dies als ein exaktes Duplikat geschlossen werden, aber wenn nicht:

Sie die GUI von einem Nicht-GUI-Thread nicht berühren. Verwenden Sie BackgroundWorker und berichten Sie den Fortschritt entsprechend, oder lesen Siefür eine direktere Kontrolle (Control.Invoke/BeginInvoke).

0

Wenn Sie das MessageReceived-Ereignis in Ihrer Agentenklasse auslösen, müssen Sie überprüfen, ob das Ziel des Ereignishandlers ISynchronizeInvoke implementiert. Wenn dies der Fall ist und die InvokeRequired-Eigenschaft true zurückgibt, müssen Sie den Eventhandler aufrufen.

Wenn Sie keine WinForms, sondern WPF verwenden, können Sie sich nicht mehr auf ISynchronizeInvoke verlassen, da die WPF-Steuerelemente diese Schnittstelle nicht implementieren. Stattdessen müssen Sie mit AsyncOperation und AsyncOperatoinManager arbeiten.

1

Sie müssen Control.Invoke (oder Control.BeginInvoke) verwenden. Erstellen Sie zuerst eine neue Windows Forms-Anwendung und fügen Sie eine Beschriftung und eine Schaltfläche hinzu. Klicken Sie doppelt auf die Schaltfläche in Visual Studio bearbeiten Veranstaltung klicken und fügen Sie den folgenden Code ein:

private void button1_Click(object sender, EventArgs e) 
    { 
     new System.Threading.Thread(new System.Threading.ThreadStart(Run)).Start(); 
    } 

    void Run() 
    { 
     label1.Invoke(new Action(delegate() 
     { 
      label1.Text = System.Threading.Thread.CurrentThread.Name + " " + System.DateTime.Now.ToString(); 
     })); 
    } 
+0

Das Schlüsselstück, das von dieser Antwort benötigt wird, ist der Anrufaufruf. – ConsultUtah