Compartilhar via


O modelo de threading de tinta

Um dos benefícios de escrever em um Tablet PC é que é muito semelhante a escrever com caneta e papel comuns. Para fazer isso, a caneta tablet coleta dados de entrada a uma taxa muito maior do que um mouse e renderiza a tinta conforme o usuário grava. O thread da interface do usuário do aplicativo não é suficiente para coletar dados da caneta e renderizar a tinta, porque ele pode ser bloqueado. Para resolver isso, um aplicativo WPF usa dois threads adicionais quando um usuário grava tinta.

A lista a seguir descreve os threads que participam na coleta e renderização da tinta digital:

  • Thread de caneta – o thread que coleta dados da caneta. (Na realidade, trata-se de um pool de threads, mas este tópico refere-se a ele como um thread de caneta.)

  • Thread da interface do usuário do aplicativo – o thread que controla a interface do usuário do aplicativo.

  • Thread de renderização dinâmica – o thread que renderiza a tinta enquanto o usuário desenha um traço. O thread de renderização dinâmica é diferente do thread que renderiza outros elementos de interface do usuário para o aplicativo, conforme mencionado no Window Presentation Foundation Threading Model.

O modelo de escrita à tinta é o mesmo, independentemente de o aplicativo usar o InkCanvas ou um controle personalizado semelhante àquele em Criar um controle de entrada de tinta. Embora este tópico discuta o threading em termos de InkCanvas, os mesmos conceitos se aplicam quando você cria um controle personalizado.

Visão geral do threading

O seguinte diagrama ilustra o modelo de threading quando um usuário desenha um traço:

Modelo de threading ao desenhar um traço.

  1. Ações que ocorrem enquanto o usuário desenha o traço

    1. Quando o usuário desenha um traço, os pontos da caneta entram no thread da caneta. Os plugins de caneta, incluindo o DynamicRenderer, aceitam os pontos da caneta no thread da caneta e têm a oportunidade de modificá-los antes que o InkCanvas os receba.

    2. O DynamicRenderer renderiza os pontos de caneta no thread de renderização dinâmica. Isso acontece ao mesmo tempo que a etapa anterior.

    3. O InkCanvas recebe os pontos de caneta no thread da interface do usuário.

  2. Ações que ocorrem após o usuário terminar o traço

    1. Quando o usuário termina de desenhar o traço, o InkCanvas cria um objeto Stroke e o adiciona ao InkPresenter, que o renderiza estaticamente.

    2. O thread da interface do usuário alerta o DynamicRenderer de que o traço é renderizado estaticamente, de modo que o DynamicRenderer remove sua representação visual do traço.

Plug-ins de caneta e coleta de tinta

Cada UIElement tem um StylusPlugInCollection. Os objetos StylusPlugIn no StylusPlugInCollection recebem e podem modificar os pontos da caneta na linha da caneta. Os objetos StylusPlugIn recebem os pontos do estilete de acordo com sua ordem no StylusPlugInCollection.

O diagrama a seguir ilustra a situação hipotética em que a coleção StylusPlugIns de uma UIElement contém stylusPlugin1, um DynamicRenderere stylusPlugin2, nessa ordem.

Ordem dos Plug-ins de Caneta afeta a saída.

No diagrama anterior, o seguinte comportamento ocorre:

  1. StylusPlugin1 modifica os valores para x e y.

  2. DynamicRenderer recebe os pontos de caneta modificados e os renderiza no thread de renderização dinâmica.

  3. StylusPlugin2 recebe os pontos de caneta modificados e modifica ainda mais os valores para x e y.

  4. O aplicativo coleta os pontos de caneta e, quando o usuário conclui o traço, renderiza estaticamente o traço.

Suponha que stylusPlugin1 restrinja os pontos de caneta a um retângulo e stylusPlugin2 traduza os pontos de caneta para a direita. No cenário anterior, o DynamicRenderer recebe os pontos da caneta restritos, mas não os pontos da caneta após o movimento. Quando o usuário desenha o traço, o traço é renderizado dentro dos limites do retângulo, mas o traço não parece ser traduzido até que o usuário levante a caneta.

Executando operações com um plug-in de caneta no thread da interface do usuário

Como testes de acertos precisos não podem ser executados no thread da caneta, alguns elementos podem, ocasionalmente, receber entradas da caneta destinadas a outros elementos. Se você precisar verificar se a entrada foi roteada corretamente antes de executar uma operação, assine e execute a operação no método OnStylusDownProcessed, OnStylusMoveProcessedou OnStylusUpProcessed. Esses métodos são invocados pelo thread do aplicativo após testes de acertos precisos terem sido executados. Para assinar esses métodos, chame o método NotifyWhenProcessed no método que ocorre no thread de caneta.

O diagrama a seguir ilustra o relacionamento entre o thread da caneta e o thread de interface do usuário com relação aos eventos de caneta de um StylusPlugIn.

Modelos de Encadeamento de Tinta (UI e Caneta)

Renderizando tinta

À medida que o usuário desenha um traço, DynamicRenderer renderiza a tinta em um thread separado para que a tinta pareça "fluir" da caneta mesmo quando o thread da interface do usuário estiver ocupado. O DynamicRenderer cria uma árvore visual no thread de renderização dinâmica à medida que coleta pontos de caneta. Quando o usuário termina o traço, o DynamicRenderer pede para ser notificado quando o aplicativo executar a próxima etapa de renderização. Depois que o aplicativo concluir a próxima passagem de renderização, o DynamicRenderer limpará sua árvore visual. O diagrama a seguir ilustra esse processo.

diagrama de encanamento de Diagrama de threading de tinta

  1. O usuário inicia o traço.

    1. O DynamicRenderer cria a árvore visual.
  2. O usuário está desenhando o traço.

    1. O DynamicRenderer cria a árvore visual.
  3. O usuário termina o traço.

    1. O InkPresenter adiciona o traço à árvore visual dele.

    2. A MIL (camada de integração de mídia) renderiza estaticamente os traços.

    3. O DynamicRenderer limpa os elementos visuais.