Microsoft-ui-xaml: Vorschlag: Automatische Weiterleitung von Ereignissen mit geänderten Eigenschaften an den UI-Thread

Erstellt am 17. Mai 2019  ·  3Kommentare  ·  Quelle: microsoft/microsoft-ui-xaml

Zusammenfassung

Lassen Sie UI-Bindungen von Eigenschaften zu, die Benachrichtigungsänderungen von einem Nicht-UI-Thread auslösen

Begründung

Wenn Sie Eigenschaften binden, müssen Sie immer eine Eigenschaftsänderungsbenachrichtigung im UI-Thread auslösen, oder Sie erhalten eine Laufzeitausnahme. Dies führt dazu, dass die Benutzeroberfläche in Ihre Ansichtsmodelle und -modelle blutet, sodass Sie den richtigen Thread aufrufen können, was Sie wiederum daran hindert, INPC aus einer .NET Standard-Bibliothek zu verwenden (es sei denn, Sie möchten in Bait'n'Switch einsteigen). .

Darüber hinaus können sich Eigenschaften während eines Frames mehrmals ändern, sodass Sie möglicherweise viel öfter zum UI-Thread springen, als wirklich erforderlich ist (alles, was erforderlich ist, ist, die Eigenschaft als "dirty" zu kennzeichnen und auf dem abgeholt zu werden nächsten Renderdurchgang.

All dies verursacht eine erhebliche zusätzliche Codekomplexität und ist fehleranfälliger.

Es verursacht auch ein Problem in WinUI 3.0, weil wir jetzt zwei UI-Threads haben: Legacy-UWP und WinUI-Threads: Auf welchem ​​soll ich etwas auslösen?

Umfang

  • Muss INotifyPropertyChanged und INotifyCollectionChanged in jedem Thread auslösen können
  • Muss in der Lage sein, es billig mehrmals als Frame zu tun, aber nur ein einziges Update auszulösen (das letzte in Gewinnen)
  • Muss in der Lage sein, eine festgelegte Eigenschaft zu verarbeiten, während sie gelesen wird, um die Benutzeroberfläche zu aktualisieren.
  • Vermeidet den Wechsel zum UI-Thread, wenn er bereits vorhanden ist.

Wichtige Notizen

Threading-Bedenken sind natürlich berechtigt, aber ich glaube nicht, dass dies am Ende wirklich ein Problem ist. Es spielt keine Rolle, dass mehrere INPC-Ereignisse ausgelöst werden, bevor die Benutzeroberfläche aktualisiert wird, da immer nur das letzte von Bedeutung wäre. Dies wäre nicht anders als der mehrfache Wechsel von vorhandenem Code zum UI-Thread. Sobald der erste zum UI-Thread wechselt, könnte die Eigenschaft bereits viele Male aktualisiert worden sein und somit der letzte gewinnen.
Natürlich müsste beim Lesen des Werts eine kurze Sperre vorhanden sein, die verhindert, dass das Dirty-Flag gesetzt wird, sodass im nächsten Frame eine zweite Runde von UI-Aktualisierungen stattfindet, falls die Eigenschaft gleichzeitig mit dem Lesen aktualisiert wird.
Wenn sich beispielsweise ein Wert von „false“ zu „true“ und zurück zu „false“ ändert, ist die Abhängigkeitseigenschaft bereits intelligent genug, um zu erkennen, dass sich der Wert nicht geändert hat, und kann optimieren, indem sie aufgrund der Eigenschaft keinen neuen Rendering-Durchgang verursacht Nicht-Änderung.

feature proposal team-Markup

Hilfreichster Kommentar

Dies ist ein sehr berechtigtes Anliegen, danke, dass Sie es angesprochen haben. Die Unterstützung von Thread-Affinität für DPs im Rahmenwerk ist möglicherweise kein großes Problem, aber sehr wohl für Implementierer von INPC.

Wenn ein Code eine Eigenschaftsänderung von einem Nicht-UI-Thread auslösen kann, bedeutet dies auch, dass der Unterstützungscode der Eigenschaft von einem Hintergrundthread geändert werden kann. Es kann mit Sperren geschützt werden, aber bidirektionale Bindungen können dann zu einem Problem werden, da sie dazu führen können, dass Eigenschaftsänderungsketten blockiert werden.

Es gibt auch das größte Problem von INPC, nämlich den Mangel an "aktuellem" Wert, als das Ereignis ausgelöst wurde. Es kann Situationen geben, in denen Eigenschaften nicht richtig synchronisiert werden (z. B. SelectedIndex und ItemsSource werden nicht synchron aktualisiert und SelectedIndex verliert seinen Wert) oder mit Ping-Pongs von Änderungen, die durch verursacht werden Eigenschaftszustände (z. B. TextBox-Änderungen und Regex-Filter).

Dies bringt dann die Probleme mit INCC mit sich, wo die gesamte Sammlung ordnungsgemäß geschützt werden muss. Beispielsweise können Sie ein Ereignis auslösen, das auf ein Element verweist, das verschoben wurde oder nicht mehr vorhanden ist.

Ich sage nicht, dass es keine Lösung für dieses Problem gibt (es gibt sie definitiv), aber IPNC-Listener, die Affinitätsänderungen einfädeln, reichen nicht aus, um dieses Problem an beiden Enden der Schnittstelle einfach zu machen.

Alle 3 Kommentare

Dies ist ein sehr berechtigtes Anliegen, danke, dass Sie es angesprochen haben. Die Unterstützung von Thread-Affinität für DPs im Rahmenwerk ist möglicherweise kein großes Problem, aber sehr wohl für Implementierer von INPC.

Wenn ein Code eine Eigenschaftsänderung von einem Nicht-UI-Thread auslösen kann, bedeutet dies auch, dass der Unterstützungscode der Eigenschaft von einem Hintergrundthread geändert werden kann. Es kann mit Sperren geschützt werden, aber bidirektionale Bindungen können dann zu einem Problem werden, da sie dazu führen können, dass Eigenschaftsänderungsketten blockiert werden.

Es gibt auch das größte Problem von INPC, nämlich den Mangel an "aktuellem" Wert, als das Ereignis ausgelöst wurde. Es kann Situationen geben, in denen Eigenschaften nicht richtig synchronisiert werden (z. B. SelectedIndex und ItemsSource werden nicht synchron aktualisiert und SelectedIndex verliert seinen Wert) oder mit Ping-Pongs von Änderungen, die durch verursacht werden Eigenschaftszustände (z. B. TextBox-Änderungen und Regex-Filter).

Dies bringt dann die Probleme mit INCC mit sich, wo die gesamte Sammlung ordnungsgemäß geschützt werden muss. Beispielsweise können Sie ein Ereignis auslösen, das auf ein Element verweist, das verschoben wurde oder nicht mehr vorhanden ist.

Ich sage nicht, dass es keine Lösung für dieses Problem gibt (es gibt sie definitiv), aber IPNC-Listener, die Affinitätsänderungen einfädeln, reichen nicht aus, um dieses Problem an beiden Enden der Schnittstelle einfach zu machen.

WPF hat das herausgefunden, also vielleicht einfach die Lösung von dort ziehen?

Toller Vorschlag. Wir tun dies für CollectionChanged-Ereignisse (etwas zufällig ...), wir sollten in der Lage sein, dasselbe für NotifyPropertyChanged zu tun.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen