Zapewnienie, że rzeczy działają na wątku UI w WPF

Buduję aplikację WPF. Robię asynchroniczną komunikację z serwerem i używam agregacji zdarzeń z Prism na kliencie. Obie te rzeczy powodują powstawanie nowych wątków, które nie są wątkiem interfejsu użytkownika. Jeśli spróbuję zrobić "operacje WPF" na tych wątkach wywołania zwrotnego i obsługi zdarzeń, świat rozpadnie się, co teraz zaczęło robić.

Najpierw napotkałem problemy przy tworzeniu obiektów WPF w wywołaniu zwrotnym z serwera. Powiedziano mi, że wątek potrzebne do uruchomienia w trybie STA. Teraz próbuję zaktualizować niektóre dane UI w obsłudze zdarzeń Prism i powiedziano mi, że:

Wywołujący nie może uzyskać dostępu do tego wątku, ponieważ posiada go inny wątek.

Więc; jaki jest klucz do poprawienia rzeczy w WPF? czytałem o Dyspozytorze WPF w ten post MSDN. Zaczynam to rozumieć, ale nie jestem jeszcze czarodziejem.

  1. jest kluczem do zawsze używanego Dispatchera.Wywoływać, gdy muszę uruchomić coś, co jestem nie jesteś pewien, czy zostanie wywołany w wątku UI?
  2. czy to ma znaczenie, czy rzeczywiście został wywołany w wątku UI, a ja mam dyspozytora.W każdym razie?
  3. Dyspozytor.Invoke = synchronously. Dispathcher.BeginInvoke = async?
  4. Will Dispatcher.Wywołaj żądanie wątku interfejsu użytkownika, a następnie zatrzymaj się, aby na niego poczekać? Czy jest to zła praktyka i ryzyko mniej reagujących programów?
  5. jak dostanę dyspozytora? Will Dispatcher.CurrentDispatcher zawsze daj mi dyspozytora reprezentujesz wątek UI?
  6. czy istnieje więcej niż jeden Dyspozytor, czy "Dyspozytor" jest zasadniczo taki sam jak wątek interfejsu dla aplikacji?
  7. a o co chodzi z tym Backgroundworkerem? Kiedy mam użyć tego zamiast tego? Zakładam, że to zawsze asynchroniczne?
  8. czy wszystko, co działa na wątku UI (przez wywołanie) będzie uruchamiane w trybie STA? Czyli jeśli mam coś, co wymaga uruchomienia w trybie STA-will Dispatcher.Czy wystarczy?

Ktoś chce mi coś wyjaśnić? Jakieś powiązane zalecenia itp.? Dzięki!

Author: tehDorf, 2010-03-04

1 answers

Przeglądając każde z twoich pytań, jeden po drugim:

  1. nie do końca; powinieneś wywoływać wątek interfejsu tylko wtedy, gdy jest to konieczne. Patrz #2.
  2. Tak, to ma znaczenie. Nie należy po prostu automatycznie Invoke wszystko. Kluczem jest wywołanie do wątku interfejsu tylko w razie potrzeby. Aby to zrobić, możesz użyć dyspozytora .Metoda CheckAccess . Zgadza się.
  3. również poprawne, i tak, ryzykujesz mniej responsywnymi programami. Przez większość czasu jesteś nie będziemy patrzeć na poważny hit wydajności (mówimy o milisekundach dla przełącznika kontekstowego), ale powinieneś tylko Invoke, jeśli to konieczne. To powiedziawszy, w niektórych punktach jest to nieuniknione, więc nie, nie powiedziałbym, że jest to zła praktyka. Jest to tylko jedno rozwiązanie problemu, który napotkasz co jakiś czas.
  4. w każdym przypadku, jaki widziałem, dokonałem należnego z Dispatcher.CurrentDispatcher. W przypadku złożonych scenariuszy może to nie wystarczyć, ale (osobiście) nie widziałem oni.
  5. Nie do końca poprawne, ale ten sposób myślenia nie zaszkodzi. Ujmę to tak:Dispatcher może być użyty do uzyskania dostępu do wątku interfejsu dla aplikacji. Ale to nie jest samo w sobie wątek UI.
  6. BackgroundWorker jest zwykle używany, gdy masz czasochłonną operację i chcesz zachować responsywny interfejs użytkownika podczas uruchamiania tej operacji w tle. Zwykle nie używasz BackgroundWorker zamiast Z Invoke, a raczej używasz BackgroundWorker w połączeniu z Invoke. Oznacza to, że jeśli chcesz zaktualizować jakiś obiekt UI w swoim BackgroundWorker, możesz wywołać wątek UI, wykonać aktualizację, a następnie powrócić do oryginalnej operacji.
  7. Tak. Wątek interfejsu aplikacji WPF, z definicji, musi być uruchomiony w mieszkaniu jednowątkowym.

Jest wiele do powiedzenia na temat BackgroundWorker, jestem pewien, że wiele pytań jest już poświęconych temu zagadnieniu, więc nie będę zagłębiał się zbytnio. Jeśli jesteś ciekawi, zajrzyj na stronę MSDN dla klasy BackgroundWorker.

 37
Author: Charlie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-07 18:12:20