Akhir-akhir ini saya sepertinya tidak bisa mendapatkan cukup dari pola async-wait yang menakjubkan dari C # 5.0. Di mana saja kau selama hidup saya?
Saya benar-benar senang dengan sintaks yang sederhana, tetapi saya mengalami satu kesulitan kecil. Masalah saya adalah bahwa fungsi-fungsi async memiliki deklarasi yang sama sekali berbeda dari fungsi-fungsi biasa. Karena hanya fungsi-fungsi async yang dapat menunggu pada fungsi-fungsi async lainnya, ketika saya mencoba untuk mem-porting beberapa kode pemblokiran lama ke async, saya mempunyai efek domino dari fungsi-fungsi yang harus saya konversi.
Orang-orang menyebut ini sebagai serangan zombie . Saat async menggigit kode Anda, kode itu akan terus bertambah besar. Proses porting tidak sulit, hanya membuang async
deklarasi dan membungkus nilai pengembaliannya Task<>
. Tapi itu menjengkelkan untuk melakukan ini berulang-ulang ketika porting kode sinkron lama.
Sepertinya saya akan jauh lebih alami jika kedua tipe fungsi (async dan sinkronisasi lama polos) memiliki sintaks yang sama persis. Jika ini masalahnya, porting akan mengambil upaya nol dan saya bisa beralih tanpa rasa sakit di antara dua bentuk.
Saya pikir ini bisa berhasil jika kita mengikuti aturan ini:
Fungsi-fungsi Async tidak membutuhkan
async
deklarasi lagi. Jenis kembali mereka tidak harus dibungkusTask<>
. Compiler akan mengidentifikasi fungsi async selama kompilasi dengan sendirinya dan melakukan pembungkus Tugas <> secara otomatis sesuai kebutuhan.Tidak ada lagi panggilan api dan lupa fungsi async. Jika Anda ingin memanggil fungsi async, Anda harus menunggu di sana. Saya jarang menggunakan api-dan-lupa, dan semua contoh kondisi balapan gila atau kebuntuan selalu tampaknya didasarkan pada mereka. Saya pikir mereka terlalu membingungkan dan "tidak terhubung" dengan pola pikir yang sinkron yang kami coba utarakan.
Jika Anda benar-benar tidak dapat hidup tanpa api-dan-lupa, akan ada sintaks khusus untuk itu. Bagaimanapun, itu tidak akan menjadi bagian dari sintaksis terpadu sederhana yang saya bicarakan.
Satu-satunya kata kunci yang Anda perlukan untuk menunjukkan panggilan asinkron adalah
await
. Jika Anda menunggu, panggilan tidak sinkron. Jika tidak, panggilannya adalah sinkron lama (ingat, kami tidak punya api dan lupakan lagi).Compiler akan mengidentifikasi fungsi-fungsi async secara otomatis (karena mereka tidak memiliki deklarasi khusus lagi). Aturan 4 membuat ini sangat mudah dilakukan - jika suatu fungsi memiliki
await
panggilan di dalamnya, itu async.
Bisakah ini bekerja? atau aku melewatkan sesuatu? Sintaksis terpadu ini jauh lebih lancar dan bisa menyelesaikan infestasi zombie sama sekali.
Beberapa contoh:
// assume this is an async function (has await calls inside)
int CalcRemoteBalanceAsync() { ... }
// assume this is a regular sync function (has no await calls inside)
int CalcRemoteBalance() { ... }
// now let's try all combinations and see what they do:
// this is the common synchronous case - it will block
int b1 = CalcRemoteBalance();
// this is the common asynchronous case - it will not block
int b2 = await CalcRemoteBalanceAsync();
// choosing to call an asynchronous function in a synchronous manner - it will block
// this syntax was used previously for async fire-and-forget, but now it's just synchronous
int b3 = CalcRemoteBalanceAsync();
// strange combination - it will block since it's calling a synchronous function
// it should probably show a compilation warning though
int b4 = await CalcRemoteBalance();
Catatan: ini merupakan kelanjutan dari diskusi terkait yang menarik di SO
sumber
await
segera melakukannya. Anda dapat melakukan sesuatu sepertivar task = FooAsync(); Bar(); await task;
. Bagaimana saya melakukan ini dalam proposal Anda?async
. Saya pikir itu salah satu keuntungan besar dariasync
-await
: bahwa ini memungkinkan Anda untuk dengan mudah menyusun operasi asinkron (dan tidak hanya dengan cara "mulai A, tunggu A, mulai B, tunggu B" yang paling sederhana). Dan sudah ada sintaks khusus persis untuk tujuan ini: itu disebutawait
.Jawaban:
Pertanyaan Anda sudah dijawab dalam pertanyaan SO yang Anda tautkan.
Ketika WinRT pertama kali keluar, para desainer menggambarkan bagaimana mereka memutuskan operasi mana yang akan menjadi async. Mereka memutuskan bahwa apa pun yang akan mengambil 50 ms atau lebih akan async, dan sisa metode akan menjadi metode biasa, non-asinkron.
Berapa banyak metode yang harus ditulis ulang agar tidak sinkron? Sekitar 10 persen dari mereka. 90% lainnya tidak terpengaruh sama sekali.
Eric Lippert kemudian menjelaskan secara rinci teknis yang cukup besar mengapa mereka memilih untuk tidak mengambil pendekatan satu ukuran untuk semua. Dia pada dasarnya mengatakan itu
async
danawait
merupakan implementasi parsial dari gaya kelanjutan-lewat, dan mengoptimalkan gaya seperti itu untuk memenuhi semua kasus adalah masalah yang sulit.sumber
async
akan menghasilkan infestasi zombie. Bahkan jika suatu metode memanggil 10 metode lain, bukankah Anda hanya perlu yangasync
tingkat atas?