Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Pola Asinkron berbasis Event memberi Anda cara yang efektif untuk mengekspos perilaku asinkron di kelas, dengan semantik event dan delegate yang akrab. Untuk menerapkan Pola Asinkron berbasis Peristiwa, Anda perlu mengikuti beberapa persyaratan perilaku tertentu. Bagian berikut menjelaskan persyaratan dan panduan yang harus Anda pertimbangkan saat menerapkan kelas yang mengikuti Pola Asinkron berbasis Peristiwa.
Untuk gambaran umum, lihat Menerapkan Pola Asinkron berbasis Peristiwa.
Jaminan Perilaku yang Diperlukan
Jika Anda menerapkan Pola Asinkron berbasis Peristiwa, Anda harus memberikan sejumlah jaminan untuk memastikan bahwa kelas Anda akan bertingkah baik dan klien kelas Anda dapat mengandalkan perilaku tersebut.
Penyelesaian
Selalu panggil handler acara MethodNameCompleted ketika Anda berhasil menyelesaikan, terjadi kesalahan, atau pembatalan. Aplikasi tidak boleh mengalami situasi di mana mereka tetap diam dan penyelesaian tidak pernah terjadi. Salah satu pengecualian untuk aturan ini adalah jika operasi asinkron itu sendiri dirancang sehingga tidak pernah selesai.
Acara yang Selesai dan EventArgs
Untuk setiap metode MethodNameAsync terpisah, terapkan persyaratan desain berikut:
Tentukan peristiwa MethodNameCompleted pada kelas yang sama dengan metode .
Tentukan kelas EventArgs dan delegasi yang menyertai untuk peristiwa MethodNameCompleted yang diturunkan dari kelas AsyncCompletedEventArgs. Nama kelas default harus dari form MethodNameCompletedEventArgs.
Pastikan kelas EventArgs khusus untuk nilai pengembalian metode MethodName . Ketika menggunakan kelas EventArgs, Anda sebaiknya tidak meminta pengembang untuk mengonversi tipe hasilnya.
Contoh kode berikut menunjukkan implementasi yang baik dan buruk dari persyaratan desain ini masing-masing.
// Good design
private void Form1_MethodNameCompleted(object sender, xxxCompletedEventArgs e)
{
DemoType result = e.Result;
}
// Bad design
private void Form1_MethodNameCompleted(object sender, MethodNameCompletedEventArgs e)
{
DemoType result = (DemoType)(e.Result);
}
Jangan tentukan kelas EventArgs untuk metode yang mengembalikan
void. Sebagai gantinya, gunakan instans dari kelas AsyncCompletedEventArgs.Pastikan Anda selalu menaikkan peristiwa MethodNameCompleted . Kejadian ini harus dinyatakan saat penyelesaian berhasil, terjadi kesalahan, atau dibatalkan. Aplikasi tidak boleh mengalami situasi di mana mereka tetap diam dan penyelesaian tidak pernah terjadi.
Pastikan Anda menangkap pengecualian apa pun yang terjadi dalam operasi asinkron dan tetapkan pengecualian yang tertangkap ke Error properti .
Jika ada kesalahan saat menyelesaikan tugas, hasilnya seharusnya tidak dapat diakses. Ketika properti Error tidak
null, pastikan bahwa mengakses properti apa pun dalam struktur EventArgs akan memicu pengecualian. RaiseExceptionIfNecessary Gunakan metode untuk melakukan verifikasi ini.Memodelkan batas waktu sebagai kesalahan. Saat waktu habis, angkat peristiwa MethodNameCompleted dan tetapkan TimeoutException ke Error properti.
Jika kelas Anda mendukung beberapa pemanggilan bersamaan, pastikan bahwa peristiwa MethodNameCompleted berisi objek yang sesuai
userSuppliedState.Pastikan bahwa peristiwa MethodNameCompleted dinaikkan pada utas yang sesuai dan pada waktu yang tepat dalam siklus hidup aplikasi. Untuk informasi selengkapnya, lihat bagian Utas dan Konteks.
Menjalankan Operasi Secara Bersamaan
Jika kelas Anda mendukung beberapa pemanggilan bersamaan, aktifkan pengembang untuk melacak setiap pemanggilan secara terpisah dengan menentukan overload MethodNameAsync yang mengambil parameter status bernilai objek, atau ID tugas, yang disebut
userSuppliedState. Parameter ini harus selalu menjadi parameter terakhir dalam tanda tangan metode MethodNameAsync .Jika kelas Anda menentukan overload MethodNameAsync yang mengambil parameter status bernilai objek, atau ID tugas, pastikan untuk melacak masa pakai operasi dengan ID tugas tersebut, dan pastikan untuk memberikannya kembali ke handler penyelesaian. Ada kelas pembantu yang tersedia untuk membantu. Untuk informasi selengkapnya tentang manajemen konkurensi, lihat Cara: Menerapkan Komponen yang Mendukung Pola Asinkron Berbasis Peristiwa.
Jika kelas Anda mendefinisikan metode MethodNameAsync tanpa parameter status, dan tidak mendukung beberapa pemanggilan bersamaan, pastikan bahwa setiap upaya untuk memanggil MethodNameAsync sebelum pemanggilan MethodNameAsync sebelumnya telah selesai memunculkan InvalidOperationException.
Secara umum, jangan menghasilkan pengecualian jika metode MethodNameAsync tanpa parameter
userSuppliedStatedipanggil beberapa kali sehingga ada beberapa operasi yang belum selesai. Anda dapat mengajukan pengecualian ketika kelas Anda secara eksplisit tidak dapat menangani situasi tersebut, tetapi asumsikan bahwa pengembang dapat menangani beberapa panggilan balik yang tidak dapat dibedakan ini
Mengakses Hasil
Jika ada kesalahan selama eksekusi operasi asinkron, hasilnya tidak boleh dapat diakses. Pastikan bahwa mengakses properti apa pun di AsyncCompletedEventArgs saat Error tidak
nullmenimbulkan pengecualian yang direferensikan oleh Error. Kelas AsyncCompletedEventArgs menyediakan RaiseExceptionIfNecessary metode untuk tujuan ini.Pastikan bahwa setiap upaya untuk mengakses hasil akan memunculkan InvalidOperationException yang menyatakan bahwa operasi dibatalkan. AsyncCompletedEventArgs.RaiseExceptionIfNecessary Gunakan metode untuk melakukan verifikasi ini.
Pelaporan Kemajuan
Mendukung pelaporan kemajuan, jika memungkinkan. Hal ini memungkinkan pengembang untuk memberikan pengalaman pengguna aplikasi yang lebih baik saat mereka menggunakan kelas Anda.
Jika Anda menerapkan peristiwa ProgressChanged atau MethodNameProgressChanged , pastikan bahwa tidak ada peristiwa seperti itu yang dinaikkan untuk operasi asinkron tertentu setelah peristiwa MethodNameCompleted operasi tersebut dinaikkan.
Jika standar ProgressChangedEventArgs sedang diisi, pastikan bahwa ProgressPercentage selalu dapat ditafsirkan sebagai persentase. Persentase tidak perlu akurat, tetapi harus mewakili persentase. Jika metrik pelaporan kemajuan Anda harus sesuatu selain persentase, turunkan kelas baru dari kelas ProgressChangedEventArgs dan biarkan ProgressPercentage tetap di 0. Hindari menggunakan metrik pelaporan selain persentase.
Pastikan bahwa peristiwa
ProgressChangeddipicu pada utas yang sesuai dan pada waktu yang tepat dalam siklus hidup aplikasi. Untuk informasi selengkapnya, lihat bagian Utas dan Konteks.
Implementasi IsBusy
Jangan mengekspos
IsBusyproperti jika kelas Anda mendukung beberapa pemanggilan bersamaan. Misalnya, proksi layanan Web XML tidak mengeksposIsBusyproperti karena mendukung beberapa pemanggilan bersamaan metode asinkron.Properti
IsBusyharus mengembalikantruesetelah metode MethodNameAsync dipanggil dan sebelum peristiwa MethodNameCompleted dilaksanakan. Jika tidak, maka seharusnya mengembalikanfalse. Komponen BackgroundWorker dan WebClient adalah contoh kelas yang mengeksposIsBusyproperti.
Pembatalan
Dukung pembatalan, jika memungkinkan. Hal ini memungkinkan pengembang untuk memberikan pengalaman pengguna aplikasi yang lebih baik saat mereka menggunakan kelas Anda.
Dalam kasus pembatalan, atur Cancelled flag pada objek AsyncCompletedEventArgs.
Pastikan bahwa setiap upaya untuk mengakses hasil akan memunculkan InvalidOperationException yang menyatakan bahwa operasi dibatalkan. AsyncCompletedEventArgs.RaiseExceptionIfNecessary Gunakan metode untuk melakukan verifikasi ini.
Pastikan bahwa panggilan ke metode pembatalan selalu berhasil dikembalikan, dan tidak pernah menimbulkan pengecualian. Secara umum, klien tidak diberi tahu apakah operasi benar-benar dapat dibatalkan pada waktu tertentu, dan tidak diberi tahu apakah pembatalan yang dikeluarkan sebelumnya telah berhasil. Namun, aplikasi akan selalu diberikan pemberitahuan ketika pembatalan berhasil, karena aplikasi mengambil bagian dalam status penyelesaian.
Memicu peristiwa MethodNameCompleted saat operasi dibatalkan.
Galat dan Pengecualian
- Tangkap pengecualian apa pun yang terjadi dalam operasi asinkron dan tetapkan nilai properti ke pengecualian tersebut AsyncCompletedEventArgs.Error .
Utas dan Konteks
Untuk pengoperasian kelas Anda yang benar, sangat penting bahwa penanganan aktivitas klien dipanggil pada utas atau konteks yang tepat untuk model aplikasi yang diberikan, termasuk aplikasi ASP.NET dan Windows Forms. Dua kelas pembantu penting disediakan untuk memastikan bahwa kelas asinkron Anda bertingkah dengan benar di bawah model aplikasi apa pun: AsyncOperation dan AsyncOperationManager.
AsyncOperationManager menyediakan satu metode, CreateOperation, yang mengembalikan AsyncOperation. Metode MethodNameAsync Anda memanggil CreateOperation dan kelas Anda menggunakan hasil yang dikembalikan AsyncOperation untuk memantau masa pakai tugas asinkron.
Untuk melaporkan kemajuan, hasil bertahap, dan penyelesaian ke klien, panggil metode Post dan OperationCompleted pada AsyncOperation. AsyncOperation bertanggung jawab untuk melakukan marshalling panggilan ke penanganan aktivitas klien ke utas atau konteks yang tepat.
Nota
Anda dapat menghindari aturan ini jika Anda secara eksplisit ingin melanggar kebijakan model aplikasi, tetapi masih mendapat manfaat dari keuntungan lain menggunakan Pola Asinkron berbasis Peristiwa. Misalnya, Anda mungkin ingin kelas yang beroperasi di Windows Forms menjadi bebas thread. Anda dapat membuat kelas berutas yang gratis, selama pengembang memahami batasan tersirat. Aplikasi konsol tidak menyinkronkan eksekusi Post panggilan. Hal ini dapat menyebabkan ProgressChanged peristiwa dinaikkan tidak berurutan. Jika Anda ingin memiliki eksekusi Post panggilan berseri, terapkan dan instal System.Threading.SynchronizationContext kelas.
Untuk informasi selengkapnya tentang menggunakan AsyncOperation dan AsyncOperationManager mengaktifkan operasi asinkron Anda, lihat Cara: Menerapkan Komponen yang Mendukung Pola Asinkron berbasis Peristiwa.
Panduan
Idealnya, setiap pemanggilan metode harus independen dari pemanggilan metode lainnya. Anda harus menghindari menggabungkan pemanggilan dengan sumber daya bersama. Jika sumber daya akan dibagikan di antara pemanggilan, Anda harus memberikan mekanisme sinkronisasi yang tepat dalam implementasi Anda.
Desain yang mengharuskan klien untuk menerapkan sinkronisasi tidak disarankan. Misalnya, Anda dapat memiliki metode asinkron yang menerima objek statis global sebagai parameter; beberapa pemanggilan bersamaan dari metode tersebut dapat mengakibatkan kerusakan data atau kebuntuan.
Jika Anda menerapkan metode dengan overload beberapa pemanggilan (
userStatedalam signature), kelas Anda harus mengelola kumpulan status-status pengguna dan ID-ID tugas yang sesuai dengan operasi-operasi tertunda mereka. Kumpulan ini harus dilindungi denganlockregion, karena beragam pemanggilan menambah dan menghapus objekuserStatedalam kumpulan.Pertimbangkan untuk menggunakan kembali kelas
CompletedEventArgsjika memungkinkan dan sesuai. Dalam kasus ini, penamaannya tidak konsisten dengan nama metode, karena delegasi tertentu dan jenis EventArgs yang diberikan tidak terkait dengan satu metode saja. Namun, memaksa pengembang untuk mentransmisikan nilai yang diambil dari properti di EventArgs tidak pernah dapat diterima.Jika Anda menulis kelas yang berasal dari Component, jangan terapkan dan instal kelas Anda sendiri SynchronizationContext . Model aplikasi, bukan komponen, mengontrol SynchronizationContext yang digunakan.
Ketika Anda menggunakan multithreading dalam bentuk apa pun, Anda berpotensi mengekspos diri Anda ke bug yang sangat serius dan kompleks. Sebelum menerapkan solusi apa pun yang menggunakan multithreading, lihat Praktik-Praktik Terbaik Utas Terkelola.
Lihat juga
- AsyncOperation
- AsyncOperationManager
- AsyncCompletedEventArgs
- ProgressChangedEventArgs
- BackgroundWorker
- Menerapkan Pola Asinkron Berbasis Peristiwa
- Pola Asinkron Berbasis Peristiwa (EAP)
- Memutuskan Kapan Harus Menerapkan Pola Asinkron Berbasis Peristiwa
- Praktik Terbaik untuk Menerapkan Pola Asinkron Berbasis Peristiwa
- Cara: Menggunakan Komponen yang Mendukung Pola Asinkron Berbasis Peristiwa
- Cara: Menerapkan Komponen yang Mendukung Pola Asinkron Berbasis Peristiwa