Mengapa C # memungkinkan Anda membuat override async?

16

Di C #, ketika Anda mengganti metode, itu diizinkan untuk membuat menimpa async ketika metode asli tidak. Ini sepertinya bentuk yang buruk.

Contoh yang membawa saya ke sini adalah ini - saya dibawa untuk membantu dengan masalah uji beban. Pada sekitar 500 pengguna secara bersamaan, proses login akan mogok dalam redirect loop. IIS sedang mencatat pengecualian dengan pesan "Modul atau pengendali asinkron selesai sementara operasi asinkron masih tertunda". Beberapa pencarian membuat saya berpikir bahwa seseorang sedang melecehkan async void, tetapi pencarian cepat saya melalui sumber tidak dapat menemukan apa pun.

Sayangnya, saya sedang mencari 'async \ svoid' (pencarian regex) ketika saya seharusnya mencari sesuatu yang lebih seperti 'async \ s [^ T]' (dengan asumsi Task tidak sepenuhnya memenuhi syarat ... Anda mengerti maksudnya).

Apa yang kemudian saya temukan adalah async override void onActionExecuting(...di basis controller. Jelas itu yang menjadi masalah, dan memang begitu. Memperbaiki itu (membuatnya sinkron untuk saat ini) menyelesaikan masalah.

Kembali ke pertanyaan: Mengapa oh mengapa Anda dapat menandai override sebagai async ketika kode panggilan tidak pernah bisa menunggu?

Peter T. LaComb Jr.
sumber
Apa yang sebenarnya menghambat penelepon untuk menunggu metode yang diganti? Saya tidak melihat kendala.
Martin Maat
@ MartinMaat Anda hanya bisa menunggu metode yang kembali Task.
Derek Elkins meninggalkan SE
Mungkin itu hal baik yang tidak saya perhatikan. Saya harus memeriksa, tetapi saya tidak ingat peringatan VS tentang memanggil metode non-async tanpa menunggu.
Peter T. LaComb Jr.

Jawaban:

16

Kata kunci async memungkinkan metode untuk menggunakan awaitsintaksis dalam definisinya. Saya bisa awaitpada metode apa pun yang mengembalikan Tasktipe terlepas dari apakah itu metode async.

voidadalah tipe pengembalian yang legal (walaupun tidak disarankan ) untuk metode async, jadi mengapa itu tidak diizinkan? Dari luar, asynctidak memungkinkan apa pun yang tidak dapat Anda lakukan tanpanya. Metode yang Anda mengalami masalah bisa saja ditulis untuk berperilaku sama persis tanpa async. Definisi itu hanya akan lebih bertele-tele.

Untuk penelepon, sebuah async Tmetode adalah metode normal yang kembali T(yang terbatas void, Taskatau Task<A>). Itu adalah metode async bukan bagian dari antarmuka. Perhatikan bahwa kode berikut ini ilegal:

interface IFoo {
    async void Bar();
}

Itu (atau kode serupa di kelas abstrak) menghasilkan pesan kesalahan berikut di VS2012:

Pengubah 'async' hanya dapat digunakan dalam metode yang memiliki tubuh pernyataan

Jika saya memang bermaksud metode dalam antarmuka atau kelas induk biasanya asinkron, saya tidak bisa menggunakannya asyncuntuk berkomunikasi itu. Jika saya ingin mengimplementasikannya dengan awaitsintaks, saya harus dapat memiliki metode override async (dalam kasus kelas induk).

Derek Elkins meninggalkan SE
sumber
1
Anda tidak menyebutkan overridesama sekali, tapi itulah pertanyaannya.
Nathan Tuggy
4
@NathanTuggy Inti dari jawabannya adalah bahwa asynctidak mengubah antarmuka metode, hanya apa yang secara sintaksis diizinkan dalam definisi, jadi apakah itu menimpa atau tidak sama sekali tidak relevan.
Derek Elkins meninggalkan SE
1
Tolong jelaskan itu, daripada menganggap semua orang sudah tahu semua yang relevan.
Nathan Tuggy
2
@ NathanTuggy Saya merasa telah menjelaskannya. Dapatkah Anda mengajukan pertanyaan spesifik tentang yang membuat Anda bingung atau membayangkan orang lain yang bingung akan bertanya? Satu-satunya hal yang dapat saya pikirkan untuk ditambahkan adalah menunjukkan bahwa asyncpengubah hanya dapat diterapkan pada implementasi. Anda tidak dapat mendeklarasikan metode async dalam suatu antarmuka, misalnya, menggarisbawahi bahwa apakah suatu metode async atau tidak bukan bagian dari antarmuka.
Derek Elkins meninggalkan SE
5
Masukkan penjelasan dalam jawabannya , maksud saya. Bukan itu tujuan komentar untuk jangka panjang.
Nathan Tuggy
10

Satu-satunya tujuan kata kunci async adalah untuk menunggu di dalam tubuh dari fungsi kata kunci tersebut. Ini diperlukan agar menambahkan fungsi menunggu tidak merusak kode yang ada. Microsoft memutuskan untuk menggunakan menunggu opsi opt-in. Untuk fungsi yang tidak ditandai async, Anda dapat menentukan variabel bernama menunggu tanpa masalah.

Oleh karena itu async bukan bagian dari tanda tangan fungsi dan tidak memiliki makna semantik dalam kode IL yang dihasilkan. Itu ada di sana untuk kompiler untuk mengetahui cara mengkompilasi fungsi dengan benar. Itu juga menginstruksikan kompiler untuk memastikan bahwa hanya Tugas, Tugas <T> atau batal yang dikembalikan.

Eric Johnson
sumber