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:
Tentukan peristiwa berikut di kelas yang sama dengan metode:
Public Event MethodNameCompleted As MethodNameCompletedEventHandler
public event MethodNameCompletedEventHandler MethodNameCompleted;
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 mengambil
userState
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 IsBusy
semantik 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:
out
parameter 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).ref
parameter 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
- ProgressChangedEventArgs
- AsyncCompletedEventArgs
- Panduan: Menerapkan Komponen yang Mendukung Pola Asinkron Berbasis Peristiwa
- Cara: Menjalankan Operasi di Latar Belakang
- Cara: Menerapkan Formulir yang Menggunakan Operasi Latar Belakang
- Memutuskan Kapan Waktu yang Tepat untuk Menerapkan Pola Asinkron Berbasis Kejadian
- Praktik Terbaik dalam Menerapkan Pola Asinkron Berbasis Peristiwa
- Pola Asinkron berbasis Peristiwa (EAP)