c# - System.InvalidOperationException
Allgemeinen
Ich bin versucht, zu schreiben eine sehr einfache TCP /IP client-server in C# eine Verbindung zu einer IP-Adresse mit einer port-Nummer, und Fragen Sie ganz einfach den Kommandozeilen-Modus, und legen Sie dann die Antworten in einer Gridbox -, Grafik-oder andere Anzeige-option.
Habe ich online geschaut und fand die downloadbar-Dienstprogramm, das gerade diese, geschrieben von Jayan Nair, und diese wird zum senden der Nachricht korrekt, und Sie erhalten die Antwort ok.
Das problem kommt, wenn ich versuchen und laden die Antwort-Daten in eine RTF-oder GridView-Steuerelements.
Die Fehlermeldung die ich bekommen hab ist :-
System.InvalidOperationException
Habe ich mich gefragt, Microsoft-Foren, und Sie haben mich sehr kompliziert, nicht eindeutig und übermäßig beteiligt Hinweis darauf, was ich tun sollte, und dazu gehört die so genannte INVOKE und BeginInvoke, und diese ganzen Dinge zu sein scheint, ein Projekt in der it;s eigenen Recht.
Was ich bin nach nur ein Beispiel, das funktioniert, ohne dass es zu kompliziert ist.
Hier der code :-
try
{
SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
int iRx = theSockId.thisSocket.EndReceive(asyn);
char[] chars = new char[iRx + 1];
System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
int charLen = d.GetChars(theSockId.dataBuffer, 0, iRx, chars, 0);
//
System.String szData = new System.String(chars);
richTextRxMessage.Text = szData; //fails
//textBox1.Text = szData; //also fails
WaitForData();
}
und hier ist die Fehlermeldung :-
base {System.Windows.Forms.TextBoxBase} = {Text = '((System.Windows.Forms.RichTextBox) (((System.Windows.Forms.RichTextBox)(richTextRxMessage)))).Text' threw an exception of type 'System.InvalidOperationException'}
Zusätzliche Informationen :-
szData enthält über 6300 Zeichen, einschließlich der Laschen (9) und zurück (13), und ist im Einklang mit der Nachricht, gesendet von dem server
Ich habe auch versucht es mit einem Textfeld anstatt RTF, Gleiches Ergebnis
Für Interessierte
Hier ist der Microsoft-link
public void OnDataReceived(IAsyncResult asyn)
{
int InputRx;
int charLen;
char[] Inputchars;
System.Text.Decoder InputDecode;
System.String szData;
bool IfInvokeRequired;
try
{
SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
InputRx = theSockId.thisSocket.EndReceive(asyn); //get size of input array
Inputchars = new char[InputRx + 1]; //put i char array
InputDecode = System.Text.Encoding.UTF8.GetDecoder();
charLen = InputDecode.GetChars(theSockId.dataBuffer, 0, InputRx, Inputchars, 0);
szData = new System.String(Inputchars);
IfInvokeRequired = richTextRxMessage.InvokeRequired;
if (IfInvokeRequired == true)
{
richTextRxMessage.Invoke((MethodInvoker)delegate { this.Text = szData; });//fails
richTextRxMessage.BeginInvoke(new MethodInvoker(() => richTextRxMessage.Text = szData));//fails as well
}
- Ich habe meine Antwort, wurde beeinflusst durch die Microsoft Antwort bereits, aber die große Frage bleibt: Ist dieses auf einem hintergrund-thread. Das ist eine sehr wichtige Frage, die völlig verändern wird meine Antwort.
- Ich denke, Sie sollten die MSDN Verweis auf die StackOverflow-Antwort ernst. Der Invoke ist eine Zeile zu beheben, nicht um ein Projekt in seinem eigenen Recht. Sie sollten auch in der Lage sein zu sagen, ob Sie sehen, ein cross-thread-Thema, oder nicht. Gibt es da eine Ausnahme?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den
InvalidOperationException
, die Sie erhalten, wird wahrscheinlich die innere Ausnahme "Die calling thread cannot access this object, da in einem anderen thread besitzt es".Gründen der Fehlersuche kann schnell
CheckForIllegalCrossThreadCalls
auf false. Dies wird stop-die run-time-werfen Sie eine Ausnahme, aber nur weil Sie nicht empfangen die Ausnahmen bedeutet nicht, dass Sie nicht stattfinden, so ist dies eine schlechte Praxis für verteilte software, aber sehr praktisch für die Fehlersuche.In Ordnung, Ihr Problem zu beheben, müssen Sie aufrufen, den code für die Interaktion mit der
RichTextBox
auf die UI-Thread aka den thread das Steuerelement erstellt wurde und der einzige thread, der erlaubt, code auszuführen, der im zusammenspiel mit der Steuerung.Aufrufen, der code im UI-Thread können Sie die folgende, lapidare Aussage:
Sehr einfach, alles, was Sie hier tun, ist die Weitergabe der Anweisung, die Sie wünschen, um nach dem aufrufen der UI-Thread durch eine Stellvertretung.
Hier ist eine Funktion benutze ich in einigen meiner Sachen;
Es ist ziemlich viel, eine nette kleine Methode für den Umgang mit jeder Art von aufrufen und reduziert den code-Zeilen, wenn Sie Sie verwenden. Um es zu verwenden, benutzen Sie einfach dieses;
Also zum Beispiel, Sie könnte verwenden;
Edit: Wie schon andere gesagt haben, dieser Fehler ist mehr als wahrscheinlich, dass durch den Zugriff auf ein Steuerelement in einem anderen thread als dem es erstellt wurde, weshalb die aufruft, erforderlich sind.
Microsoft Antwort ist nicht ganz falsch, aber es gibt andere Möglichkeiten, es zu tun, die sind etwas einfacher, obwohl Sie nicht Aussehen es.
Hier ist ein snippit aus meinem eigenen code, die möglicherweise nützlich für Sie.
Hinweis, wie
InvokeRequired
und diedirtyImage.Invoke(...)
verwendet werden. Ich mache es viel einfacher, durch die Schaffung der Delegierten und mit einer Methode, invoker, so kann ich alle Anrufe Zwischenlagen. die Stellvertretung im wesentlichen erstellt eine mini-Methode, die dann aufgerufen wird, mit dem MethodInvoker. Denn die Veränderungen sind auf dem UI-thread, obwohl, Sie können nicht aufgerufen werden von einem hintergrund-thread, ohne mit.Invoke
nicht gestattet.Die Art und Weise Ihre Anrufe könnte verändert werden, so ist:
dieser Aufruf funktioniert auch direkt aus dem UI-thread sich selbst, so dass Sie nicht wirklich BRAUCHEN, die if-Anweisung, aber es Bezug auf die "Kosten", der langsamer als der Aufruf der Eigenschaften direkt.
Natürlich ist dies nur der macht wirklich einen Unterschied, wenn Sie auf einen hintergrund-thread zu beginnen. Wenn nicht, dann müssen Sie prüfen, den Fehler selbst. Vielleicht gibt es etwas falsch mit dem text der Rückkehr, schreibt Sie in eine Datei und schauen Sie es, sehen Sie, wenn Sie können vor Ort das problem. Versuchen Sie, den text der RTB-manuell, zu sehen, ob es auch erlaubt zu geschehen. etc etc und so weiter.
dirtyImage.Invoke((MethodInvoker)delegate {Visible = RigX.IsDirty; Refresh();});
. Auch ich persönlich würde eine...Invoked
Methode für alles, was mehr als 1 Befehl, da haben Sie nur 1 Stückchen code überprüfen/ändern.Das Problem ist wahrscheinlich, weil von multi-threading, wie vorgeschlagen, auf die MS Foren. Wie beantragen Sie diese operation in einer asynchronen Art und Weise, es wird ein weiterer thread, der die Eingaben verarbeiten, so dass Sie Hauptanwendungs-thread nicht blockiert.
Um dieses Problem zu beheben müssen Sie
Invoke
das Steuerelement, dessen Eigenschaft Sie ändern möchten. Diese benötigen Sie, wie Ihre wichtigsten Anwendungs-thread besitzt die UI, und jede operation auf dem UI ausgeführt werden kann nicht aus einem anderen thread.Den aufrufen ist nicht kompliziert, und kann in ein paar Zeilen.
Ändern Sie die folgende Zeile
zu
Dieser code fragt den main-ui-thread zu aktualisieren den text für
richTextRxMessage
eher als es zu tun selbst.