Udostępnij przez


Model wątkowania tuszu

Jedną z zalet atramentu na tablecie jest to, że odczucie jest bardzo podobne do pisania zwykłym piórem na papierze. W tym celu pióro na tablecie zbiera dane wejściowe z znacznie większą szybkością niż mysz i renderuje atrament podczas zapisywania przez użytkownika. Wątek interfejsu użytkownika aplikacji nie jest wystarczający do zbierania danych pióra i renderowania tuszu, ponieważ może zostać zablokowany. Aby rozwiązać ten problem, aplikacja WPF używa dwóch dodatkowych wątków, gdy użytkownik pisze atramentem.

Na poniższej liście opisano wątki, które biorą udział w zbieraniu i renderowaniu cyfrowego atramentu:

  • Wątek pióra — ten, który pobiera dane wejściowe z rysika. (W rzeczywistości jest to pula wątków, ale ten temat odnosi się do niego jako "pen thread").

  • Wątek interfejsu użytkownika aplikacji — wątek, który kontroluje interfejs użytkownika aplikacji.

  • Dynamiczny wątek renderowania — wątek, który renderuje atrament, podczas gdy użytkownik rysuje pociągnięcie. Wątek renderowania dynamicznego różni się od wątku, który renderuje inne elementy interfejsu użytkownika dla aplikacji, jak wspomniano w artykule Window Presentation Foundation Threading Model.

Model pisma odręcznego jest taki sam, niezależnie od tego, czy aplikacja używa InkCanvas, czy niestandardowej kontrolki podobnej do kontrolki w Tworzenie kontrolki wprowadzania pisma odręcznego. Chociaż w tym temacie omawia się wątki w kontekście InkCanvas, te same pojęcia mają zastosowanie podczas tworzenia kontroli niestandardowej.

Omówienie wątków

Na poniższym diagramie przedstawiono model wątków, gdy użytkownik rysuje pociągnięcie:

Model wątkowania podczas rysowania pociągnięcia.

  1. Akcje wykonywane podczas rysowania linii przez użytkownika

    1. Gdy użytkownik rysuje pociągnięcie, punkty rysika pojawiają się na wątku pióra. Wtyczki rysika, w tym DynamicRenderer, akceptują punkty rysika w wątku pióra i mają możliwość ich zmodyfikowania przed odebraniem ich przez InkCanvas.

    2. DynamicRenderer renderuje punkty rysików w wątku renderowania dynamicznego. Dzieje się to w tym samym czasie co poprzedni krok.

    3. InkCanvas otrzymuje punkty rysika w wątku interfejsu użytkownika.

  2. Akcje podejmowane po tym, jak użytkownik zakończy kreskę

    1. Gdy użytkownik zakończy rysowanie pociągnięcia, InkCanvas tworzy obiekt Stroke i dodaje go do InkPresenter, który statycznie go renderuje.

    2. Wątek interfejsu użytkownika powiadamia DynamicRenderer, że pociągnięcie jest statycznie renderowane, więc DynamicRenderer usuwa jego wizualną reprezentację pociągnięcia.

Kolekcja tuszu i wtyczki do rysika

Każdy UIElement ma StylusPlugInCollection. Obiekty StylusPlugIn w StylusPlugInCollection odbierają i mogą modyfikować punkty rysika w wątku pisaka. Obiekty StylusPlugIn otrzymują punkty dotykowe zgodnie z ich kolejnością w StylusPlugInCollection.

Na poniższym diagramie przedstawiono hipotetyczną sytuację, w której kolekcja StylusPlugIns z UIElement zawiera stylusPlugin1, DynamicRendereri stylusPlugin2w tej kolejności.

Kolejność wtyczek Stylus ma wpływ na dane wyjściowe.

Na poprzednim diagramie odbywa się następujące zachowanie:

  1. StylusPlugin1 modyfikuje wartości x i y.

  2. DynamicRenderer odbiera zmodyfikowane punkty rysika i renderuje je w wątku renderowania dynamicznego.

  3. StylusPlugin2 otrzymuje zmodyfikowane punkty rysika i dodatkowo modyfikuje wartości x i y.

  4. Aplikacja zbiera punkty rysika, a gdy użytkownik zakończy pociągnięcie, renderuje je jako statyczny obraz.

Załóżmy, że stylusPlugin1 ogranicza punkty rysika do prostokąta i stylusPlugin2 przesuwa punkty rysika w prawo. W poprzednim scenariuszu DynamicRenderer otrzymuje ograniczone punkty rysika, ale nie przekazane punkty rysika. Gdy użytkownik rysuje pociągnięcie, pociągnięcie jest renderowane w granicach prostokąta, ale pociągnięcie nie wydaje się być tłumaczone, dopóki użytkownik nie podniesie pióra.

Wykonywanie operacji za pomocą wtyczki Stylus w wątku interfejsu użytkownika

Ponieważ nie można wykonać dokładnego sprawdzania precyzyjności trafień w wątku pióra, niektóre elementy mogą czasami otrzymywać dane wejściowe rysika przeznaczone dla innych elementów. Jeśli musisz upewnić się, że dane wejściowe zostały prawidłowo kierowane przed wykonaniem operacji, zasubskrybuj i wykonaj operację w metodzie OnStylusDownProcessed, OnStylusMoveProcessedlub OnStylusUpProcessed. Te metody są wywoływane przez wątek aplikacji po przeprowadzeniu dokładnego testowania trafień. Aby zasubskrybować te metody, wywołaj metodę NotifyWhenProcessed w ramach metody, która jest uruchamiana w wątku pióra.

Na poniższym diagramie przedstawiono relację między wątkiem pióra a wątkiem interfejsu użytkownika w kontekście zdarzeń rysika StylusPlugIn.

modele wątkowe pisma odkowego (UI i pióra)

Renderowanie tuszu

Gdy użytkownik rysuje pociągnięcie, DynamicRenderer renderuje atrament w osobnym wątku, dzięki czemu atrament wydaje się płynąć z pióra, nawet gdy wątek interfejsu użytkownika jest zajęty. DynamicRenderer tworzy drzewo wizualne w wątku renderowania dynamicznego, gdy zbiera punkty rysika. Gdy użytkownik zakończy pociągnięcie, DynamicRenderer poprosi o powiadomienie, gdy aplikacja wykona kolejne renderowanie. Po zakończeniu następnego renderowania aplikacja DynamicRenderer czyści drzewo wizualne. Na poniższym diagramie przedstawiono ten proces.

diagram przeciągu tuszu InkThreading_VisualTree

  1. Użytkownik rozpoczyna rysowanie.

    1. DynamicRenderer tworzy drzewo wizualne.
  2. Użytkownik rysuje pociągnięcie.

    1. DynamicRenderer kompiluje drzewo wizualne.
  3. Użytkownik kończy pociągnięcie.

    1. InkPresenter dodaje pociągnięcie do drzewa wizualnego.

    2. Warstwa integracji multimediów (MIL) statycznie renderuje pociągnięcia.

    3. DynamicRenderer czyści wizualizacje.