Jaga agar utas UI tetap responsif

Pengguna mengharapkan aplikasi Anda tetap responsif saat melakukan komputasi, terlepas dari jenis komputer. Ini berarti hal yang berbeda untuk aplikasi yang berbeda - menyediakan fisika realistis, memuat data dari disk atau web, menyajikan adegan kompleks, menavigasi antar halaman, atau memproses data. Terlepas dari jenis komputasi, pengguna ingin aplikasi Anda bertindak berdasarkan input mereka dan menghilangkan instans yang tampaknya tidak responsif.

Aplikasi Anda digerakkan oleh peristiwa: kode Anda melakukan pekerjaan sebagai respons terhadap peristiwa dan kemudian duduk diam hingga peristiwa berikutnya. Kode platform untuk UI (tata letak, input, dan memicu event) serta kode UI aplikasi Anda berjalan pada utas UI yang sama. Hanya satu instruksi yang dijalankan pada utas tersebut pada satu waktu, jadi jika kode aplikasi Anda membutuhkan waktu terlalu lama untuk memproses peristiwa, kerangka kerja tidak dapat menjalankan tata letak atau menaikkan peristiwa baru. Responsivitas aplikasi Anda bergantung pada ketersediaan utas UI untuk memproses tugas.

Anda perlu menggunakan utas UI untuk membuat hampir semua perubahan pada elemen UI. Anda tidak dapat memperbarui UI dari utas latar belakang, tetapi Anda dapat memposting pesan dengan DispatcherQueue.TryEnqueue untuk menyebabkan kode berjalan di sana.

Important

Di aplikasi desktop WinUI 3, gunakan DispatcherQueue alih-alih UWP CoreDispatcher. Akses antrean dispatcher melalui properti jendela DispatcherQueue Anda atau DispatcherQueue.GetForCurrentThread().

Note

Utas render terpisah dapat menerapkan perubahan UI yang tidak memengaruhi cara input ditangani atau tata letak dasar. Misalnya, banyak animasi dan transisi yang tidak memengaruhi tata letak dapat berjalan pada utas render ini.

Penundaan instansiasi elemen

Beberapa tahap paling lambat dalam aplikasi termasuk memulai dan beralih tampilan. Jangan melakukan lebih banyak pekerjaan daripada yang diperlukan untuk memunculkan UI yang dilihat pengguna pada awalnya. Misalnya, jangan membuat UI untuk konten yang ditampilkan secara bertahap maupun isi pop-up.

  • Gunakan atribut x:Load untuk menunda-instantiate elemen.
  • Sisipkan elemen secara terprogram ke pohon sesuai permintaan.

Gunakan DispatcherQueue.TryEnqueue dengan prioritas rendah untuk mengantrikan pekerjaan agar diproses oleh utas UI saat sedang tidak sibuk.

Menggunakan API asinkron

Untuk menjaga aplikasi Anda tetap responsif, gunakan versi API asinkron saat tersedia. API asinkron memastikan bahwa utas eksekusi aktif Anda tidak pernah terblokir dalam waktu yang lama. Saat Anda memanggil API dari utas UI, selalu gunakan versi asinkron jika ada.

Alihkan pekerjaan ke utas latar belakang

Tulis penanganan aktivitas untuk kembali dengan cepat. Jika ada pekerjaan yang cukup besar yang perlu dilakukan, jadwalkan di utas latar belakang lalu kembali.

Anda dapat menjadwalkan pekerjaan secara asinkron dengan menggunakan await operator di C#. Namun, await tidak menjamin bahwa proses tersebut dijalankan di utas latar belakang. Banyak API SDK Aplikasi Windows menjadwalkan tugas pada utas latar belakang untuk Anda, tetapi jika Anda memanggil kode aplikasi Anda hanya dengan menggunakan await, metode tersebut akan dijalankan pada utas UI. Anda harus secara eksplisit menjalankan kode aplikasi di utas latar belakang. Di C#, selesaikan ini dengan meneruskan kode ke Task.Run.

Ingatlah bahwa Anda hanya dapat mengakses elemen UI dari utas UI. Gunakan utas UI untuk mengakses elemen UI sebelum meluncurkan pekerjaan latar belakang, atau gunakan DispatcherQueue.TryEnqueue pada utas latar belakang untuk memposting pembaruan UI kembali ke utas UI.

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.
    }
}

Dalam contoh ini, NextMove_Click handler kembali di await untuk menjaga utas UI tetap responsif. Eksekusi dilanjutkan di penangan tersebut setelah ComputeNextMove (yang berjalan di utas latar belakang) selesai, dan sisa kode memperbarui UI dengan hasilnya.