Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Użytkownicy oczekują, że aplikacja będzie reagować podczas wykonywania obliczeń, niezależnie od typu maszyny. Oznacza to różne rzeczy dla różnych aplikacji — zapewniając realistyczną fizykę, ładowanie danych z dysku lub sieci Web, prezentowanie złożonych scen, nawigowanie między stronami lub przetwarzanie danych. Niezależnie od typu obliczeń użytkownicy chcą, aby aplikacja działała na ich danych wejściowych i eliminuje wystąpienia, w których wydaje się nie odpowiadać.
Aplikacja jest sterowana zdarzeniami: kod wykonuje pracę w odpowiedzi na zdarzenie, a następnie pozostaje w stanie bezczynności do następnego zdarzenia. Kod platformy obsługujący interfejs użytkownika (układ, obsługa danych wejściowych, wywoływanie zdarzeń) oraz kod interfejsu użytkownika aplikacji działają w tym samym wątku interfejsu użytkownika. Tylko jedna instrukcja jest wykonywana w tym wątku jednocześnie, więc jeśli kod aplikacji trwa zbyt długo, aby przetworzyć zdarzenie, platforma nie może uruchomić układu ani zgłosić nowych zdarzeń. Responsywność aplikacji zależy od dostępności wątku interfejsu użytkownika do przetwarzania zadań.
Aby wprowadzić prawie wszystkie zmiany w elementach interfejsu użytkownika, musisz użyć wątku interfejsu użytkownika. Nie można zaktualizować interfejsu użytkownika z wątku w tle, ale możesz opublikować do niego komunikat za pomocą polecenia DispatcherQueue.TryEnqueue , aby spowodować uruchomienie tam kodu.
Ważna
W aplikacjach komputerowych WinUI 3 użyj DispatcherQueue zamiast rozwiązania UWP CoreDispatcher. Uzyskaj dostęp do kolejki dyspozytora za pośrednictwem właściwości okna DispatcherQueue lub DispatcherQueue.GetForCurrentThread().
Note
Oddzielny wątek renderowania może stosować zmiany interfejsu użytkownika, które nie wpływają na sposób obsługi danych wejściowych lub układu podstawowego. Na przykład wiele animacji i przejść, które nie wpływają na układ, może być uruchamianych w tym wątku renderowania.
Opóźnienie inicjowania elementu
Niektóre z najwolniejszych etapów w aplikacji obejmują uruchamianie i przełączanie widoków. Nie rób więcej pracy niż jest to konieczne, aby wyświetlić interfejs użytkownika, który użytkownik widzi początkowo. Na przykład, nie twórz interfejsu użytkownika dla treści ujawnianych stopniowo ani treści wyskakujących okienek.
- Użyj atrybutu x:Load, aby opóźnić tworzenie elementów.
- Programowe wstawianie elementów do drzewa na żądanie.
Użyj DispatcherQueue.TryEnqueue z niskim priorytetem, aby kolejkować pracę wątku interfejsu użytkownika do przetwarzania, gdy nie jest zajęty.
Używanie asynchronicznych interfejsów API
Aby zachować czas reakcji aplikacji, użyj asynchronicznych wersji interfejsów API, gdy są dostępne. Asynchroniczne API zapewnia, że aktywny wątek wykonania nigdy nie zostaje zablokowany na dłuższy czas. Podczas wywoływania interfejsu API z wątku interfejsu użytkownika zawsze używaj wersji asynchronicznej, jeśli istnieje.
Przenoszenie zadań do wątków działających w tle
Zapisywanie procedur obsługi zdarzeń w celu szybkiego powrotu. Gdy trzeba wykonać znaczną ilość pracy, zaplanuj jej wykonanie w wątku działającym w tle, a następnie wróć.
Możesz zaplanować pracę asynchronicznie przy użyciu await operatora w języku C#. Jednak await nie gwarantuje, że zadanie jest wykonywane w tle. Wiele interfejsów API pakietu Zestaw SDK do aplikacji systemu Windows planuje wykonanie pracy w tle, ale jeśli wywołasz kod swojej aplikacji, używając tylko await, ta metoda zostanie uruchomiona w wątku interfejsu użytkownika. Musisz jawnie uruchomić kod aplikacji w wątku w tle. W języku C#wykonaj ten krok, przekazując kod do task.Run.
Pamiętaj, że dostęp do elementów interfejsu użytkownika można uzyskać tylko z wątku interfejsu użytkownika. Użyj wątku interfejsu użytkownika, aby uzyskać dostęp do elementów interfejsu użytkownika przed uruchomieniem pracy w tle, lub użyj DispatcherQueue.TryEnqueue w wątku w tle, aby przekazać aktualizacje interfejsu użytkownika z powrotem do wątku interfejsu użytkownika.
public sealed partial class MainWindow : Window
{
// Declared in MainWindow.xaml as x:Name="statusText".
private TextBlock statusText;
private async void NextMove_Click(object sender, RoutedEventArgs e)
{
// The await causes the handler to return immediately.
await Task.Run(() => ComputeNextMove());
// Now update the UI with the results.
// This code runs on the UI thread after ComputeNextMove completes.
statusText.Text = "Move computed.";
}
private void ComputeNextMove()
{
// Perform background work here.
// Don't directly access UI elements from this method.
}
}
W tym przykładzie procedura obsługi NextMove_Click zwraca sterowanie w elemencie await, aby zapewnić responsywność wątku interfejsu użytkownika. Wykonanie jest następnie wznawiane w tym programie obsługi po zakończeniu działania ComputeNextMove (które jest uruchamiane w wątku w tle), a pozostały kod aktualizuje interfejs użytkownika wynikami.