Model wątkowości typu atrament

Jedną z zalet atramentu na tablecie jest to, że czuje się bardzo jak pisanie z zwykłym piórem i papierem. 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 pisma oddyskowego, ponieważ może zostać zablokowany. Aby rozwiązać ten problem, aplikacja WPF używa dwóch dodatkowych wątków, gdy użytkownik zapisuje atrament.

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

  • Wątek pióra — wątek, 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 wątku pióra).

  • 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. Dynamiczny wątek renderowania różni się od wątku, który renderuje inne elementy interfejsu użytkownika dla aplikacji, jak wspomniano w temacie Window Presentation Foundation Threading Model (Model wątkowy platformy Window Presentation Foundation).

Model pisma odręcznego jest taki sam, czy aplikacja używa kontrolki InkCanvas niestandardowej lub podobnej do tej w temacie Tworzenie kontrolki wprowadzania pisma odręcznego. Chociaż w tym temacie omówiono wątki w kategoriach InkCanvas, te same pojęcia mają zastosowanie podczas tworzenia kontrolki niestandardowej.

Omówienie wątków

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

Threading model while drawing a stroke.

  1. Akcje występujące podczas ściągnięcia pociągnięcia przez użytkownika

    1. Gdy użytkownik rysuje pociągnięcie, punkty rysika pojawiają się w 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 InkCanvas .

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

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

  2. Akcje występujące po zakończeniu pociągnięcia przez użytkownika

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

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

Kolekcja pisma odwrotowego i wtyczki Stylus

Każda z nich UIElement ma element StylusPlugInCollection. Obiekty StylusPlugIn w odbieraniu StylusPlugInCollection i mogą modyfikować punkty rysika w wątku pióra. Obiekty StylusPlugIn otrzymują punkty rysika zgodnie z ich kolejnością w obiekcie StylusPlugInCollection.

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

Order of Stylus Plugins affect output.

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 program odbiera 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, statycznie renderuje pociągnięcie.

Załóżmy, że stylusPlugin1 ogranicza to rysik do prostokąta i stylusPlugin2 tłumaczy rysik na prawo. W poprzednim scenariuszu otrzymuje DynamicRenderer ograniczone punkty rysika, ale nie przetłumaczone 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 przeprowadzić dokładnego testowania trafień w wątku pióra, niektóre elementy mogą od czasu do czasu odbierać 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 metodzie, która występuje w wątku pióra.

Na poniższym diagramie przedstawiono relację między wątkiem pióra a wątkiem interfejsu użytkownika w odniesieniu do zdarzeń stylus elementu StylusPlugIn.

Ink Threading Models (UI and Pen)

Renderowanie pisma oddyskowego

Gdy użytkownik rysuje pociągnięcie, renderuje atrament na osobnym wątku, DynamicRenderer więc atrament wydaje się "przepływać" z pióra nawet wtedy, gdy wątek interfejsu użytkownika jest zajęty. Obiekt DynamicRenderer tworzy drzewo wizualne w wątku renderowania dynamicznego, ponieważ zbiera punkty rysika. Gdy użytkownik zakończy pociągnięcie, DynamicRenderer zostanie wyświetlony monit o powiadomienie, gdy aplikacja wykona następne renderowanie. Po zakończeniu następnego renderowania DynamicRenderer aplikacja czyści drzewo wizualne. Na poniższym diagramie przedstawiono ten proces.

Ink threading diagram

  1. Użytkownik rozpoczyna pociągnięcie.

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

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

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

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

    3. Element DynamicRenderer czyści wizualizacje.