Frage

Ich schreibe eine WinForms-Anwendung, die zwei Modi: Konsole oder GUI. Drei Projekte innerhalb der gleichen Lösung, eine für die Konsolenanwendung, eine für die UI-Formulare und die dritte, die Logik zu halten, die die beiden Schnittstellen beide zu verbinden. Die Konsole App läuft absolut reibungslos.

Ein Modell, das die Benutzer-Auswahl hält, hat es eine IList<T> wo T ein lokales Objekt ist, Step, die INotifyPropertyChanged implementiert, so in der Benutzeroberfläche dies auf einen Datagridview montiert ist. Alle zur Laufzeit ist in Ordnung, wird der Anfangszustand der Objekte auf dem Bildschirm reflektiert wird.

Jeder der Step Objekte ist eine Aufgabe, die wiederum durchgeführt wird; einige der Eigenschaften ändern wird, zurück in die IList reflektiert wird und auf die Datagridview weitergegeben.

Diese Aktion in den UI-Versionen wird durch die Schaffung eines Background getan Ereignisse zurück auf die UI zu erhöhen. Die Step tut es Sache und erzeugt ein StepResult Objekt, das ist ein Aufzählungstyp ein Ergebnis anzeigt (zB Laufen, NotRun, OK, notok, Caveat) und eine Zeichenfolge, die eine Nachricht anzuzeigen (weil der Schritt lief aber nicht ganz wie erwartet, also mit ein Caveat). Normalerweise werden die Aktionen eine Datenbank Interaktion beinhalten, aber im Debug-Modus ich zufällig ein Ergebnis erzeugen.

Wenn die Meldung null ist, gibt es kein Problem, aber wenn ich erzeugen eine Antwort wie folgt:

StepResult returnvalue = new StepResult(stat, "completed with caveat")

Ich erhalte eine Fehlermeldung, dass die Datagridview von einem anderen Thread als der Thread zugegriffen wurde es erstellt wurde. (Ich bin vorbei dies durch einen benutzerdefinierten Handler, die die rufenden behandeln sollen, wenn erforderlich - vielleicht ist es nicht)

Dann, wenn ich erzeugen eine einzigartige Reaktion, z.B. unter Verwendung einer Zufallszahl r:

StepResult returnvalue = new StepResult(stat, r.ToString());

die Aktionen ohne Probleme erfolgreich zu sein, werden die Zahlen sauber auf die Datagridview geschrieben.

Ich bin verwirrt. Ich gehe davon aus, es ist irgendwie ein Stringliteral Problem, aber kann jemand mit einer klareren Erklärung kommen?

War es hilfreich?

Lösung

Da Sie tun UI über Ereignisabonnement Bindung Sie können diese Informationen hilfreich finden; Es ist ein Beispiel, das ich schreibe vor einiger Zeit das zeigt, wie BindingList<T> Unterklasse, so dass die Meldungen automatisch an den UI-Thread gemarshallt werden.

Wenn es kein Sync-Kontext (das heißt Konsolenmodus), dann kehrt sie zurück zu der einfachen direkten invoke, so gibt es keinen Overhead. Wenn in UI-Thread ausgeführt wird, beachten Sie, dass diese im Wesentlichen Control.Invoke verwendet, die selbst läuft nur die Delegierten direkt, wenn es auf dem UI-Thread ist. So gibt es nur jeder Schalter, wenn die Daten von einem nicht-UI-Thread bearbeitet wird - juts, was wir wollen ;-p

Andere Tipps

Sie haben Ihre eigene quesion beantwortet: -

  

Ich erhalte eine Fehlermeldung, dass die Datagridview von einem anderen Thread als der Thread zugegriffen wurde es erstellt wurde.

WinForms besteht darauf, dass alle Aktionen auf Formen und Kontrollen im Zusammenhang mit dem Gewinde fertig sind die Form erstellt wurde. Der Grund für diese Anlage ist, hat aber mit dem zugrunde liegenden Win32-API eine Menge zu tun. Weitere Einzelheiten finden Sie die verschiedenen Einträge auf Die Blog Old New Thing.

Was Sie tun müssen, um die InvokeRequired ist zu verwenden und Methoden aufrufen, um sicherzustellen, dass die Kontrollen werden immer aus dem gleichen Thread (pseudocodeish) zugegriffen:

object Form.SomeFunction (args)
{
  if (InvokeRequired)
  {
    return Invoke (new delegate (Form.Somefunction), args);
  }
  else
  {
    return result_of_some_action;
  }
}

Ich hatte das gleiche Problem vor. Vielleicht helfen kann dieser Artikel, den ich über sie geschrieben.

http: //cyberkruz.vox .com / library / Post / net-Problem-Asynchron-und-windows-Forms.html

ich diesen Artikel gefunden - " Aktualisieren IBindingList von anderem Thread " -, die mit dem Finger auf die Binding spitz -

  

Da das Binding ist nicht Setup für Asynchron-Operationen, müssen Sie den Binding aus dem gleichen Thread aktualisieren, dass es wurde kontrolliert auf.

Explizit Bestehen der Mutter Form als ISynchronizeInvoke Objekt und die Schaffung einen Wrapper für den BindingList<T> des Trick.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top