Praktik terbaik dalam pemrograman asinkron .Net

Pemrograman asinkron memungkinkan Anda melakukan operasi I / O yang intensif sumber daya tanpa harus memblokir thread utama atau yang menjalankan aplikasi. Meskipun bermanfaat dan tampaknya mudah diterapkan, hal ini memiliki banyak kerumitan dan risiko. Potensi risiko yang terkait dengan pemrograman asinkron, terutama penggunaan pemrograman asinkron dengan cara yang salah dengan tidak mengikuti praktik yang disarankan, termasuk kebuntuan, proses mogok, dan bahkan kinerja yang lambat. Anda juga harus mahir menulis, men-debug kode async.

Hindari tipe pengembalian kosong dalam metode asinkron

Sebuah metode di C # dibuat sebagai metode asynchronous menggunakan kata kunci async dalam tanda tangan metode. Anda dapat memiliki satu atau lebih kata kunci await di dalam metode async. Kata kunci menunggu digunakan untuk menunjukkan titik penangguhan. Metode asinkron di C # dapat memiliki salah satu dari jenis pengembalian berikut: Tugas, Tugas, dan void. Kata kunci "await" digunakan dalam metode async untuk memberi tahu kompilator bahwa metode tersebut dapat memiliki titik penangguhan dan dimulainya kembali.

Perhatikan bahwa saat menggunakan TPL, yang setara dengan mengembalikan kekosongan di TPL adalah Tugas asinkron. Anda harus menyadari bahwa async void hanya dan seharusnya digunakan untuk kejadian async. Jika Anda menggunakannya di tempat lain, Anda akan mengalami kesalahan. Dengan kata lain, metode async yang memiliki void sebagai tipe kembalian tidak disarankan. karena metode async yang mengembalikan void memiliki semantik berbeda saat Anda bekerja dengan pengecualian dalam aplikasi Anda.

Saat pengecualian terjadi dalam metode async yang memiliki tipe kembalian dari Tugas atau Tugas, objek pengecualian disimpan di dalam objek Tugas. Sebaliknya, jika Anda memiliki metode asinkron dengan tipe pengembalian void, tidak ada objek Tugas yang terkait. Pengecualian seperti itu dimunculkan pada SynchronizationContext yang aktif pada saat metode asynchronous dipanggil. Dengan kata lain, Anda tidak dapat menangani pengecualian yang dimunculkan dalam metode async void menggunakan penangan pengecualian yang ditulis di dalam metode asinkron. Metode asinkron yang memiliki tipe kembalian void juga sulit diuji karena perbedaan dalam semantik penanganan kesalahan ini. Untuk informasi Anda, kelas SynchronizationContext di ruang nama System.Threading mewakili konteks sinkronisasi di .Net dan membantu Anda mengantrekan tugas ke konteks lain.

Daftar kode berikut menggambarkan hal ini. Anda memiliki dua metode yaitu, Test dan TestAsync, dan yang terakhir memberikan pengecualian.

public class AsyncDemo

   {

       public void Test()

       {

           try

           {

               TestAsync();

           }

           catch (Exception ex)

           {

               Console.WriteLine(ex.Message);

           }

       }

       private async void TestAsync()

       {

           throw new Exception("This is an error message");

       }

   }

Berikut adalah cara membuat instance kelas AsyncDemo dan menjalankan metode Test.

static void Main(string[] args)

       {

           AsyncDemo obj = new AsyncDemo();

           obj.Test();

           Console.Read();

       }

Metode pengujian membuat panggilan ke metode TestAsync dan panggilan tersebut dibungkus di dalam blok coba-tangkap dengan maksud menangani pengecualian yang dilempar ke dalam metode TestAsync. Namun, pengecualian yang dilempar ke dalam metode TestAsync tidak akan pernah tertangkap, yaitu ditangani di dalam metode pemanggil Test.

Hindari mencampurkan kode asinkron dan sinkron

Anda tidak boleh memiliki campuran kode sinkron dan asinkron. Memblokir kode asinkron dengan melakukan panggilan ke Task.Wait atau Task.Result adalah praktik pemrograman yang buruk. Saya akan merekomendasikan menggunakan kode asinkron ujung ke ujung - ini adalah cara teraman untuk menghindari kesalahan agar tidak masuk.

Anda dapat menghindari kebuntuan dengan menggunakan. ConfigureAwait(continueOnCapturedContext: false)kapan pun Anda menelepon untuk menunggu. Jika Anda tidak menggunakan ini, metode async akan memblokir pada titik di mana await dipanggil. Dalam hal ini Anda hanya memberi tahu penunggu agar tidak menangkap konteks saat ini. Saya akan mengatakan bahwa ini adalah praktik yang baik untuk menggunakan .ConfigureAwait (false) kecuali Anda memiliki alasan khusus untuk tidak menggunakannya.

Saya akan membahas lebih lanjut tentang pemrograman asynchronous di posting blog saya yang akan datang di sini. Untuk informasi lebih lanjut tentang praktik terbaik dalam pemrograman asynchronous, Anda dapat merujuk ke artikel hebat Stephen Cleary di MSDN.