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.
- 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?
- czy to ma znaczenie, czy rzeczywiście został wywołany w wątku UI, a ja mam dyspozytora.W każdym razie? Dyspozytor.Invoke = synchronously. Dispathcher.BeginInvoke = async?
- 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?
- jak dostanę dyspozytora? Will Dispatcher.CurrentDispatcher zawsze daj mi dyspozytora reprezentujesz wątek UI?
- czy istnieje więcej niż jeden Dyspozytor, czy "Dyspozytor" jest zasadniczo taki sam jak wątek interfejsu dla aplikacji?
- a o co chodzi z tym Backgroundworkerem? Kiedy mam użyć tego zamiast tego? Zakładam, że to zawsze asynchroniczne?
- 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!
1 answers
Przeglądając każde z twoich pytań, jeden po drugim:
- nie do końca; powinieneś wywoływać wątek interfejsu tylko wtedy, gdy jest to konieczne. Patrz #2. Tak, to ma znaczenie. Nie należy po prostu automatycznie
- 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. - 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.
Nie do końca poprawne, ale ten sposób myślenia nie zaszkodzi. Ujmę to tak: -
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.
Tak. Wątek interfejsu aplikacji WPF, z definicji, musi być uruchomiony w mieszkaniu jednowątkowym.
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ę.
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.
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.
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