W tym odcinku będzie o Manage application responsiveness – czyli Dispatcher

DispatcherObject

Większość obiektów w WPF dziedziczy po tej właśnie klasie a przez to niestety nie są thread-safety. Jeśli chcemy zmieniać właściwości tych obiektów z innego wątku niż ten w którym zostały utworzone, musimy posłużyć się specjalnym mechanizmem. Na szczęście klasa ta udostępnia specjalną właściwość Dispatcher, którą możemy wykorzystać do tego celu.

Przykładowy kod, który możemy do tego celu wykorzystać:

void method(object obj)

{

    var przycisk = (obj as Button);

    if (przycisk == null) return;

    if (przycisk.Dispatcher.CheckAccess()) // 1

    {

        przycisk.Content = “Update z wątku”;

    }

    else

    {

        przycisk.Dispatcher.Invoke(DispatcherPriority.Normal,

                            new Action<Button>(method), obj); //2

    }           

}

Najważniejsze są tu linie 1 oraz 2. W 1 sprawdzamy, czy jesteśmy w tym samym wątku, w którym została utworzona nasza kontrolka przycisk i jeśli tak to zmieniamy właściwość kontrolki. Jeśli nie używamy obiektu Dispatcher to wywołania naszej metody (2).

DispatcherPriority

W przypadku WPF’a mamy całkiem sporo możliwości konfigurowania priorytetu naszej aplikacji. Enumeracja DispatcherPriority oferuje, aż 12 różnych wartości. Znaleźć je wszystkie możemy na MSDN. Na początku ilość może przytłaczać, ale dzięki takiemu rozróżnieniu możemy precyzyjnie zaplanować nasze wątki.

Zwracanie wartości z wątków

Jeśli nasza metoda zwraca wartość to w głównym wątku możemy chcieć ją odczytać. Aby to zrobić możemy posłużymy się mniej więcej takim kodem:

   var result = Dispatcher.BeginInvoke(new Func<object, bool>(method), przycisk);

   result.Wait();   

   MessageBox.Show(result.Result.ToString());

Freezable Objects

Obiekty, które dziedziczą z tej klasy mogą znaleźć się w specjalnym stanie “zamrożenia”, w którym dostępne są tylko do odczytu. Są wtedy również thread-safe. Aby sprawdzić czy czy dany obiekt jest zamrożony wystarczy zawołać właściwość IsFrozen, aby sprawdzić czy obiekt może zostać zamrożony CanBeFrozen.Przykładowe klasy to: Brush, Pen, Geometry, Transform, AnimationTimeline.Po co takie obiekty nam są? Ponoć poprawiają wydajność naszych aplikacji w WPF oraz udostępniają szczegółowe notyfikacje o swoim stanie.

Następnym razem nowy temat – Building user interfaces. Zaczniemy od Content controls.