Microsoft-ui-xaml: Proposta: a propriedade de despacho automático alterou os eventos para o encadeamento da interface do usuário

Criado em 17 mai. 2019  ·  3Comentários  ·  Fonte: microsoft/microsoft-ui-xaml

Resumo

Permitir que ligações de interface do usuário aconteçam a partir de propriedades que geram alterações de notificação de qualquer thread que não seja de interface do usuário

Justificativa

Ao vincular propriedades, você sempre deve gerar uma notificação de alteração de propriedade no Thread da interface do usuário ou obterá uma exceção de tempo de execução. Isso faz com que a interface do usuário sangre em seus modelos e modelos de exibição, para que você possa aumentar no thread adequado, o que, por sua vez, impede que você use o INPC de uma biblioteca .NET Standard (a menos que você queira entrar no bait'n'switch) .

Além disso, você pode ter propriedades mudando várias vezes durante um quadro, então você pode pular para o thread de interface do usuário muito mais vezes do que é realmente necessário (tudo o que é necessário é sinalizar a propriedade como "suja" e ser pego no próxima passagem de renderização.

Tudo isso causa complexidade de código significativamente extra e é mais propenso a erros.

Isso também causa um problema no WinUI 3.0, porque agora temos dois threads de interface do usuário: UWP herdado e threads WinUI: em qual devo aumentar?

Alcance

  • Deve ser capaz de gerar INotifyPropertyChanged e INotifyCollectionChanged em qualquer thread
  • Deve ser capaz de fazer isso de forma barata várias vezes por frame, mas apenas acionando uma única atualização (a última em vitórias)
  • Deve ser capaz de lidar com uma propriedade que está sendo definida enquanto está sendo lida para atualizar a interface do usuário.
  • Evita alternar para o thread de interface do usuário se ele já estiver nele.

Anotações importantes

As preocupações com threads são obviamente válidas, mas não acredito que isso seja realmente um problema no final. Não importa que vários eventos INPC sejam acionados antes das atualizações da interface do usuário, pois apenas o último importaria. Isso não seria diferente do código existente alternando para o Thread de IU várias vezes. Uma vez que o primeiro mude para o UI Thread, a propriedade já pode ter sido atualizada muitas vezes e, portanto, o último em vitórias.
Naturalmente, seria necessário haver um bloqueio curto quando o valor é lido para impedir que o sinalizador sujo seja definido, portanto, uma segunda rodada de atualizações da interface do usuário ocorre no próximo quadro, caso a propriedade seja atualizada ao mesmo tempo em que está sendo lida.
Na verdade, se um valor, por exemplo, mudar de falso, para verdadeiro e de volta para falso, a propriedade de dependência já é inteligente o suficiente para detectar que o valor não foi alterado e pode otimizar não causando uma nova passagem de renderização devido à propriedade não mudança.

feature proposal team-Markup

Comentários muito úteis

Esta é uma preocupação muito válida, obrigado por levantar. Suporte de afinidade de thread para DPs no framework pode não ser um grande problema, mas pode muito bem ser para implementadores do INPC.

Se algum código for capaz de gerar uma alteração de propriedade de um thread que não seja da interface do usuário, isso também significa que o código de suporte da propriedade pode ser alterado de um thread em segundo plano. Ele pode ser protegido usando bloqueios, mas as ligações bidirecionais podem se tornar um problema, pois podem tornar as cadeias de alteração de propriedade impasses.

Há também o maior problema do INPC, que é a falta de valor "atual" quando o evento foi levantado. Pode haver situações em que as propriedades não sejam sincronizadas corretamente (por exemplo, SelectedIndex e ItemsSource não são atualizados de forma síncrona e SelectedIndex perde seu valor), ou com ping-pongs de alterações causadas por estados de propriedade (por exemplo, alterações TextBox e filtros regex).

Isso traz então os problemas com o INCC, onde todo o acervo precisa ser protegido adequadamente. Por exemplo, você pode gerar um evento referenciando um item que foi movido ou não está mais lá.

Não estou dizendo que não há solução para esse problema (certamente há), mas os ouvintes do IPNC encadeando as alterações de afinidade não são suficientes para facilitar esse problema em ambas as extremidades da interface.

Todos 3 comentários

Esta é uma preocupação muito válida, obrigado por levantar. Suporte de afinidade de thread para DPs no framework pode não ser um grande problema, mas pode muito bem ser para implementadores do INPC.

Se algum código for capaz de gerar uma alteração de propriedade de um thread que não seja da interface do usuário, isso também significa que o código de suporte da propriedade pode ser alterado de um thread em segundo plano. Ele pode ser protegido usando bloqueios, mas as ligações bidirecionais podem se tornar um problema, pois podem tornar as cadeias de alteração de propriedade impasses.

Há também o maior problema do INPC, que é a falta de valor "atual" quando o evento foi levantado. Pode haver situações em que as propriedades não sejam sincronizadas corretamente (por exemplo, SelectedIndex e ItemsSource não são atualizados de forma síncrona e SelectedIndex perde seu valor), ou com ping-pongs de alterações causadas por estados de propriedade (por exemplo, alterações TextBox e filtros regex).

Isso traz então os problemas com o INCC, onde todo o acervo precisa ser protegido adequadamente. Por exemplo, você pode gerar um evento referenciando um item que foi movido ou não está mais lá.

Não estou dizendo que não há solução para esse problema (certamente há), mas os ouvintes do IPNC encadeando as alterações de afinidade não são suficientes para facilitar esse problema em ambas as extremidades da interface.

O WPF descobriu isso, então talvez apenas puxe a solução de lá?

Ótima sugestão. Fazemos isso para eventos CollectionChanged (um pouco por acidente...), devemos ser capazes de fazer o mesmo para NotifyPropertyChanged.

Esta página foi útil?
0 / 5 - 0 avaliações