Share via


Menerapkan Pola Asinkron Berbasis Peristiwa

Jika Anda menulis kelas dengan beberapa operasi yang mungkin menimbulkan penundaan yang nyata, pertimbangkan untuk memberikan fungsionalitas asinkron dengan menerapkan Pola Asinkron berbasis Peristiwa.

Pola Asinkron berbasis Peristiwa menyediakan cara standar untuk mengemas kelas yang memiliki fitur asinkron. Jika diimplementasikan dengan kelas pembantu seperti AsyncOperationManager, kelas Anda akan berfungsi dengan benar di bawah model aplikasi apa pun, termasuk ASP.NET, aplikasi Konsol, dan aplikasi Formulir Windows.

Untuk contoh yang mengimplementasikan Pola Asinkron berbasis Peristiwa, lihat Cara: Menerapkan Komponen yang Mendukung Pola Asinkron Berbasis Peristiwa.

Untuk operasi asinkron sederhana, Anda mungkin menemukan komponen yang BackgroundWorker cocok. Untuk informasi selengkapnya tentang BackgroundWorker, lihat Cara: Menjalankan Operasi di Latar Belakang.

Daftar berikut menjelaskan fitur Pola Asinkron berbasis Peristiwa yang dibahas dalam topik ini.

  • Peluang untuk Menerapkan Pola Asinkron Berbasis Peristiwa

  • Penamaan Metode Asinkron

  • Pembatalan Dukungan Opsional

  • Secara opsional Mendukung Properti IsBusy

  • Opsional Memberikan Dukungan untuk Pelaporan Kemajuan

  • Opsional Memberikan Dukungan untuk Mengembalikan Hasil yang Bertambah Bertahap

  • Menangani Parameter Out dan Ref dalam Metode

Peluang untuk Menerapkan Pola Asinkron Berbasis Peristiwa

Pertimbangkan untuk menerapkan Pola Asinkron berbasis Peristiwa ketika:

  • Klien kelas Anda tidak perlu WaitHandle dan IAsyncResult objek tersedia untuk operasi asinkron, yang berarti bahwa polling dan WaitAll atau WaitAny perlu dibangun oleh klien.

  • Anda ingin operasi asinkron dikelola oleh klien dengan model peristiwa / delegasi yang sudah dikenal.

Setiap operasi adalah kandidat untuk implementasi asinkron, tetapi yang Anda harapkan akan mengalami latensi panjang harus dipertimbangkan. Terutama yang tepat adalah operasi ketika klien memanggil metode dan diberitahu pada penyelesaian, tanpa intervensi lebih lanjut yang diperlukan. Juga sesuai adalah operasi yang berjalan terus menerus, secara berkala memberi tahu klien tentang kemajuan, hasil yang bertambah bertahap, atau perubahan status.

Untuk informasi selengkapnya tentang memutuskan kapan harus mendukung Pola Asinkron Berbasis Peristiwa, lihat Memutuskan Kapan Menerapkan Pola Asinkron Berbasis Peristiwa.

Penamaan Metode Asinkron

Untuk setiap metode sinkron MethodName yang ingin Anda sediakan pasangan asinkronnya:

Tentukan metode MethodNameAsync yang:

  • Menampilkan void.

  • Mengambil parameter yang sama dengan metode MethodName.

  • Menerima beberapa doa.

Secara opsional tentukan overloadMethodNameAsync, identik dengan MethodNameAsync, tetapi dengan parameter bernilai objek tambahan yang disebut userState. Lakukan ini jika Anda siap untuk mengelola beberapa pemanggilan bersamaan metode Anda, dalam hal ini userState nilai akan dikirimkan kembali ke semua penanganan aktivitas untuk membedakan pemanggilan metode. Anda juga dapat memilih untuk melakukan ini hanya sebagai tempat untuk menyimpan status pengguna untuk pengambilan nanti.

Untuk setiap tanda tangan metode MethodNameAsync terpisah:

  1. Tentukan peristiwa berikut di kelas yang sama dengan metode:

    Public Event MethodNameCompleted As MethodNameCompletedEventHandler
    
    public event MethodNameCompletedEventHandler MethodNameCompleted;
    
  2. Tentukan delegasi berikut dan AsyncCompletedEventArgs. Ini kemungkinan akan ditentukan di luar kelas itu sendiri, tetapi dalam namespace layanan yang sama.

    Public Delegate Sub MethodNameCompletedEventHandler( _
        ByVal sender As Object, _
        ByVal e As MethodNameCompletedEventArgs)
    
    Public Class MethodNameCompletedEventArgs
        Inherits System.ComponentModel.AsyncCompletedEventArgs
    Public ReadOnly Property Result() As MyReturnType
    End Property
    
    public delegate void MethodNameCompletedEventHandler(object sender,
        MethodNameCompletedEventArgs e);
    
    public class MethodNameCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
    {
        public MyReturnType Result { get; }
    }
    
    • Pastikan bahwa kelas MethodNameCompletedEventArgs mengekspos anggotanya sebagai properti baca-saja, dan bukan bidang, karena bidang mencegah pengikatan data.

    • Jangan tentukan kelas turunan apa pun AsyncCompletedEventArgsuntuk metode yang tidak menghasilkan hasil. Cukup gunakan instans itu AsyncCompletedEventArgs sendiri.

      Catatan

      Ini dapat diterima dengan sempurna, jika layak dan sesuai, untuk menggunakan kembali delegasi dan AsyncCompletedEventArgs jenis. Dalam hal ini, penamaan tidak akan konsisten dengan nama metode, karena delegasi tertentu dan AsyncCompletedEventArgs tidak akan terikat dengan satu metode.

Pembatalan Dukungan Opsional

Jika kelas Anda akan mendukung pembatalan operasi asinkron, pembatalan harus diekspos ke klien seperti yang dijelaskan di bawah ini. Ada dua poin keputusan yang perlu dicapai sebelum menentukan dukungan pembatalan Anda:

  • Apakah kelas Anda, termasuk penambahan yang diantisipasi di masa mendatang, hanya memiliki satu operasi asinkron yang mendukung pembatalan?
  • Dapatkah operasi asinkron yang mendukung pembatalan mendukung beberapa operasi yang tertunda? Artinya, apakah metode MethodNameAsync mengambiluserState parameter, dan apakah memungkinkan beberapa pemanggilan sebelum menunggu apa pun selesai?

Gunakan jawaban atas dua pertanyaan ini pada tabel di bawah ini untuk menentukan apa tanda tangan untuk metode pembatalan Anda seharusnya.

Visual Basic

Beberapa Operasi Simultan Didukung Hanya Satu Operasi pada Satu Waktu
Satu Operasi Asinkron di seluruh kelas Sub MethodNameAsyncCancel(ByVal userState As Object) Sub MethodNameAsyncCancel()
Beberapa Operasi Asinkron di kelas Sub CancelAsync(ByVal userState As Object) Sub CancelAsync()

C#

Beberapa Operasi Simultan Didukung Hanya Satu Operasi pada Satu Waktu
Satu Operasi Asinkron di seluruh kelas void MethodNameAsyncCancel(object userState); void MethodNameAsyncCancel();
Beberapa Operasi Asinkron di kelas void CancelAsync(object userState); void CancelAsync();

Jika Anda menentukan CancelAsync(object userState) metode, klien harus berhati-hati saat memilih nilai status mereka untuk membuatnya mampu membedakan di antara semua metode asinkron yang dipanggil pada objek, dan bukan hanya di antara semua pemanggilan metode asinkron tunggal.

Keputusan untuk memberi nama versi operasi asinkron tunggal MethodNameAsyncCancel didasarkan pada kemampuan untuk lebih mudah menemukan metode di lingkungan desain seperti IntelliSense Visual Studio. Ini mengelompokkan anggota terkait dan membedakan mereka dari anggota lain yang tidak ada hubungannya dengan fungsionalitas asinkron. Jika Anda mengharapkan bahwa mungkin ada operasi asinkron tambahan yang ditambahkan dalam versi berikutnya, lebih baik untuk menentukan CancelAsync.

Jangan menentukan beberapa metode dari tabel di atas di kelas yang sama. Itu tidak akan masuk akal, atau itu akan mengacaukan antarmuka kelas dengan proliferasi metode.

Metode ini biasanya akan segera kembali, dan operasi mungkin atau mungkin tidak benar-benar membatalkan. Dalam penanganan aktivitas untuk peristiwa MethodNameCompleted, objek MethodNameCompletedEventArgs berisi Cancelled bidang, yang dapat digunakan klien untuk menentukan apakah pembatalan terjadi.

Mematuhi semantik pembatalan yang dijelaskan dalam Praktik Terbaik untuk Menerapkan Pola Asinkron Berbasis Peristiwa.

Secara opsional Mendukung Properti IsBusy

Jika kelas Anda tidak mendukung beberapa pemanggilan bersamaan, pertimbangkan untuk mengekspos IsBusy properti. Ini memungkinkan pengembang untuk menentukan apakah metode MethodNameAsync berjalan tanpa menangkap pengecualian dari metode MethodNameAsync.

Mematuhi IsBusysemantik yang dijelaskan dalam Praktik Terbaik untuk Menerapkan Pola Asinkron berbasis Peristiwa.

Opsional Memberikan Dukungan untuk Pelaporan Kemajuan

Hal ini sering diinginkan untuk operasi asinkron untuk melaporkan kemajuan selama operasi. Pola Asinkron berbasis Peristiwa memberikan pedoman untuk melakukannya.

  • Secara opsional menentukan peristiwa yang akan dinaikkan oleh operasi asinkron dan dipanggil pada utas yang sesuai. Objek ProgressChangedEventArgs membawa indikator kemajuan bernilai bilangan bulat yang diharapkan antara 0 dan 100.

  • Beri nama peristiwa ini sebagai berikut:

    • ProgressChanged jika kelas memiliki beberapa operasi asinkron (atau diharapkan tumbuh untuk menyertakan beberapa operasi asinkron dalam versi mendatang);

    • MethodNameProgressChanged jika kelas memiliki satu operasi asinkron.

    Pilihan penamaan ini sejajar dengan metode pembatalan, seperti yang dijelaskan di bagian Pembatalan Dukungan Opsional.

Kejadian ini harus menggunakan ProgressChangedEventHandler tanda tangan delegasi dan ProgressChangedEventArgs kelas. Atau, jika indikator kemajuan yang lebih spesifik domain dapat disediakan (misalnya, byte dibaca dan total byte untuk operasi pengunduhan), maka Anda harus menentukan kelas turunan dari ProgressChangedEventArgs.

Perhatikan bahwa hanya ada satu ProgressChanged atau peristiwa MethodNameProgressChanged untuk kelas, terlepas dari jumlah metode asinkron yang didukungnya. Klien diharapkan menggunakan userState objek yang diteruskan ke metode MethodNameAsync untuk membedakan di antara pembaruan kemajuan pada beberapa operasi bersamaan.

Mungkin ada situasi ketika beberapa operasi mendukung kemajuan dan masing-masing mengembalikan indikator yang berbeda untuk kemajuan. Dalam hal ini, satu ProgressChanged peristiwa tidak sesuai, dan Anda dapat mempertimbangkan untuk mendukung beberapa ProgressChanged peristiwa. Dalam hal ini gunakan pola penamaan MethodNameProgressChanged untuk setiap metode MethodNameAsync.

Mematuhi semantik pembatalan yang dijelaskan dalam Praktik Terbaik untuk Menerapkan Pola Asinkron Berbasis Peristiwa.

Opsional Memberikan Dukungan untuk Mengembalikan Hasil yang Bertambah Bertahap

Terkadang operasi asinkron dapat mengembalikan hasil yang bertambah bertahap sebelum selesai. Ada sejumlah opsi yang dapat digunakan untuk mendukung skenario ini. Beberapa contoh mengikuti.

Kelas operasi tunggal

Jika kelas Anda hanya mendukung satu operasi asinkron, dan operasi tersebut dapat mengembalikan hasil yang bertambah bertahap, maka:

  • Perluas ProgressChangedEventArgs jenis untuk membawa data hasil yang bertambah bertahap, dan tentukan peristiwa MethodNameProgressChanged dengan data yang diperluas ini.

  • Naikkan peristiwa MethodNameProgressChanged ini ketika ada hasil yang bertambah bertahap untuk dilaporkan.

Solusi ini berlaku khusus untuk kelas operasi asinkron tunggal karena tidak ada masalah dengan peristiwa yang sama yang terjadi untuk mengembalikan hasil yang bertambah bertahap pada "semua operasi", seperti yang dilakukan peristiwa MethodNameProgressChanged.

Kelas Multioperasi dengan Hasil yang Bertambah Bertahap Homogen

Dalam hal ini, kelas Anda mendukung beberapa metode asinkron, masing-masing mampu mengembalikan hasil yang bertambah bertahap, dan hasil yang bertambah bertahap ini semuanya memiliki jenis data yang sama.

Ikuti model yang dijelaskan di atas untuk kelas operasi tunggal, karena struktur yang sama EventArgs akan berfungsi untuk semua hasil yang bertambah bertahap. Tentukan ProgressChanged peristiwa alih-alih peristiwa MethodNameProgressChanged, karena berlaku untuk beberapa metode asinkron.

Kelas Multioperasi dengan Hasil yang Bertambah Bertahap Heterogen

Jika kelas Anda mendukung beberapa metode asinkron, masing-masing mengembalikan jenis data yang berbeda, Anda harus:

  • Pisahkan pelaporan hasil yang bertambah bertahap Anda dari pelaporan kemajuan Anda.

  • Tentukan peristiwa MethodNameProgressChanged terpisah dengan yang sesuai EventArgs untuk setiap metode asinkron untuk menangani data hasil yang bertambah bertahap dari metode tersebut.

Panggil penanganan aktivitas tersebut pada utas yang sesuai seperti yang dijelaskan dalam Praktik Terbaik untuk Menerapkan Pola Asinkron Berbasis Peristiwa.

Menangani Parameter Out dan Ref dalam Metode

Meskipun penggunaan out dan ref, secara umum, tidak disarankan dalam .NET, berikut adalah aturan yang harus diikuti ketika ada:

Diberikan metode sinkron MethodName:

  • outparameter ke MethodName tidak boleh menjadi bagian dari MethodNameAsync. Sebaliknya, parameter tersebut harus menjadi bagian dari MethodNameCompletedEventArgs dengan nama yang sama dengan parameternya yang setara dalam MethodName (kecuali ada nama yang lebih sesuai).

  • refparameter ke MethodName akan muncul sebagai bagian dari MethodNameAsync, dan sebagai bagian dari MethodNameCompletedEventArgs dengan nama yang sama dengan parameternya yang setara dalam MethodName (kecuali ada nama yang lebih tepat).

Misalnya, diberikan:

Public Function MethodName(ByVal arg1 As String, ByRef arg2 As String, ByRef arg3 As String) As Integer
public int MethodName(string arg1, ref string arg2, out string arg3);

Metode asinkron Anda dan kelasnya AsyncCompletedEventArgs akan terlihat seperti ini:

Public Sub MethodNameAsync(ByVal arg1 As String, ByVal arg2 As String)

Public Class MethodNameCompletedEventArgs
    Inherits System.ComponentModel.AsyncCompletedEventArgs
    Public ReadOnly Property Result() As Integer
    End Property
    Public ReadOnly Property Arg2() As String
    End Property
    Public ReadOnly Property Arg3() As String
    End Property
End Class
public void MethodNameAsync(string arg1, string arg2);

public class MethodNameCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
{
    public int Result { get; };
    public string Arg2 { get; };
    public string Arg3 { get; };
}

Lihat juga