Äquivalent von PostMessage in C# für die Synchronisation mit dem Hauptthread mit MVVM?
Muss ich zurückgeblieben mit der Suche, weil hier ein scheinbar häufiges problem, dass ich nicht in der Lage zu lösen.
Hier ist mein problem -- ich verwende WPF und MVVM, und ich habe eine statemachine, die ausgeführt wird, in das Modell. Wenn ein Fehler Auftritt, muss ich weiterleiten information an das ViewModel, um den Fehler anzuzeigen. Dieser Teil scheint zu funktionieren okay. Wenn der Benutzer auf das gewünschte Verhalten, wird der code in das Modell weiterhin, und schaut auf das Objekt, das der Benutzer interagiert mit zu bestimmen, was als Nächstes zu tun ist.
Das problem ist, dass das Modell braucht zum laden einer Datei, die aktualisiert die GUI, die mit dem Inhalt der besagten Datei. Da das Modell die Ausführung in einem thread, kann man sich vorstellen, was werde ich als Nächstes Fragen -- wie zur Hölle Sie die Synchronisierung mit dem GUI richtig? In MFC, hätte ich entweder SendMessage oder PostMessage zu erreichen, die GUI zu aktualisieren.
Habe ich Lesen Sie Artikel für WinForms legen nahe, dass mithilfe von InvokeRequired automatisch Aufruf von BeginInvoke, wenn nötig. Ich konnte ja nicht wissen, dass BeginInvoke erfüllen würde, was ich wollte, also wurde ich ermutigt, das zu lernen.
Wie kann ich eigentlich Aufruf von BeginInvoke von meinem Modell? Funktioniert diese Methode auch anwenden zu WPF? Ich ging weiter und implementiert einen Delegierten und rief dann Aufrufen, aber ich bekomme die gleiche Fehlermeldung, die mir sagt, die Auflistung kann nicht geändert werden, aus diesem thread. Ich habe auch versucht BeginInvoke für die Hölle der es, aber ich gehe davon aus, dass auch nicht funktionieren würde, weil es würde nur starten, aus einem anderen thread sowieso.
Verwirrt. Wenn ich etwas verpasst haben offensichtlich wirklich, dass die veröffentlicht worden ist über alle über das internet, gehen Sie vor und geben Sie mir eine verbale Auspeitschung, die ich wahrscheinlich haben es sich verdient.
BEARBEITEN - ich sollte wohl noch hinzufügen, dass ich bin auf der Suche nach etwas anderes als ein timer oder BackgroundWorker-basierte Lösung, es sei denn, dass die nur Weg, um dieses Problem zu lösen in WPF /MVVM. Außerdem Frage ich mich, wenn eine der MVVM-toolkits hätte-Einrichtungen für diese Art der Sache schon...
- Um es klarzustellen: ich nehme an, Sie waren einfach aufrufen von Invoke() auf die Delegierte direkt, anstatt Dispatcher.Invoke()? Die erste wird einfach ausgeführt die Delegierten auf dem gleichen thread, der zweite Marschall der Anruf an den Dispatcher thread (die möglicherweise oder möglicherweise nicht vorhanden, je nach Art der Anwendung verbraucht dein ViewModel).
- Wayne, du hast Recht. Ich war nur grob nach dem Artikel, und ich Frage mich, ob die Tatsache, dass es für WinForms ist, warum Ihr Beispiel funktioniert? Wie auch immer, ich denke, Franci war richtig und ich übergeben zu müssen, in einen Dispatcher mit allen notwendigen Mitteln. 🙂 Vielen Dank für Ihre Zeit. Hoffentlich kann ich das bald gelöst.
- Seine möglich, Sie nutzen könnten MVVMLights Messenger-Klasse zum senden einer Nachricht an die GUI ohne den Umweg über die Vielseitigkeit. Sie würde immer noch gehen durch den Dispatcher, wenn der Code Hinter berührt eine der tatsächlichen Benutzeroberfläche. Ich bin ein wenig verwirrt, da Databinding geht schon durch den Dispatcher warum ist das ein Problem. Wenn dein Thread aktualisiert eine gebundene Eigenschaft auf der Ansicht, es sollte automatisch gemarshallt werden, um das UI, ohne ein problem.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn Sie möchten, planen Sie einige arbeiten von einem hintergrund-thread in den UI-thread im WPF, verwenden Sie die
DispatcherObject
. Hier ist ein schöner Artikel, wie Erstellen von Responsive Apps mit dem Dispatcher.Update: Beachten Sie, dass wenn Sie ein Ereignis zum senden von Benachrichtigungen von der Model-ViewModel, Sie müssen noch Schalter an den UI-thread irgendwo. Ob dieser Schalter sollte sich in der Modell oder das ViewModel ist ein gutes design diskutieren, aber es ist orthogonal zu Ihrer Frage.
Wird das Ereignis ausgelöst, auf das entsprechende Dispatcher-thread. Seit Sie brauchen, um in den UI-thread ist, müssen Sie verwenden ein Dispatcher, der erstellt wird, auf dem UI-thread. Der einfachste Weg ist die Nutzung des
DispatcherObject.Dispatcher
- Eigenschaft auf einem von der UI-Elemente. Die alternative ist die Erstellung einer in Ihrem Modell oder ViewModel. Wenn Sie ein design-purist, würde ich vorschlagen, Sie erstellen die Dispatcher in Ihrem Modell und dem Versand der Anruf wieder zurück an den UI-thread, bevor Sie das Ereignis auslösen, auf die das ViewModel ist das Zuhören. Auf diese Weise haben alle das thread-switching und management enthalten ist, in das Model und das ViewModel arbeiten als ein single-threaded auf dem UI-thread nur.Ich denke, dass Ihr ViewModel sollte wirklich nicht wissen, etwas über die Sicht, einschließlich der Frage, ob oder nicht es ist eine WPF-Benutzeroberfläche, oder, ob oder nicht, die UI hat sogar das Konzept von einem Dispatcher-thread, so dass die rote fahne Fliegen sollten, sobald Sie beginnen das schreiben von code in deinem ViewModel, dass der Versuch der CheckAccess() oder InvokeRequired um Marschall code zum UI-thread. Stattdessen würde ich das Modell ein Ereignis auslösen, das die Ansicht hören kann und aktualisieren sich entsprechend, oder haben das ViewModel eine Eigenschaft verfügbar machen (zB. bool FileIsLoading), dass die Ansicht einfach an sich bindet, um zu erkennen und zu zeigen, was das Modell tut, asynchron, und es ist das ViewModel zuständig, um zu gewährleisten, dass der Wert der Eigenschaft korrekt ist.
Beispiel:
Habe ich einen anderen Ansatz, der zu funktionieren scheint, und ich wollte einfach nur werfen es da draußen zu bekommen, einige Kommentare (falls jemand auch das Lesen dieser Frage mehr!).
Begann ich dann mit dem MVVM Light Toolkit Bote die Klasse, und es scheint wirklich gut zu funktionieren für mich. Zum Beispiel, nehmen Sie die ProgressBar-Komponente als Beispiel. Ich habe mich registriert, zwei Nachrichten mit meinem ViewModel für die Einstellung der progress-Wert und maximale Fortschritte. Dann in meinem Modell, denn es legt die Aufgaben und den gesamten Prozess, es sendet diese Nachrichten. Wenn der VM die Nachrichten empfängt, ist es nur updates, Datenbindung-Werte, und meine GUI updates automatisch! Es ist super duper leicht, aber ich Frage mich, was Sie alle dachten über diesen Ansatz. Ist jemand anderes tut dies ohne Zwischenfälle?