Bagaimana kalau tidak memiliki kata kunci?
Saya ingin kompiler menyadari bahwa, sebagian besar waktu, ketika saya memanggil metode asinkron, saya ingin hasilnya.
Document doc = DownloadDocumentAsync();
Itu dia. Alasan orang mengalami kesulitan memikirkan kata kunci untuk hal ini adalah karena itu seperti memiliki kata kunci untuk "lakukan hal yang akan Anda lakukan jika semuanya normal". Itu harus menjadi default, tidak memerlukan kata kunci.
Memperbarui
Saya awalnya menyarankan kompiler harus pintar dengan inferensi tipe untuk mencari tahu apa yang harus dilakukan. Berpikir lebih jauh tentang ini, saya akan menjaga implementasi yang ada di CTP seperti apa adanya, tetapi membuat beberapa tambahan sepele untuk itu, sehingga untuk mengurangi kasus di mana Anda harus menggunakan await
kata kunci secara eksplisit.
Kami menciptakan sebuah atribut: [AutoAwait]
. Ini hanya dapat diterapkan pada metode. Salah satu cara untuk menerapkan ini pada metode Anda adalah menandainya async
. Tetapi Anda juga bisa melakukannya dengan tangan, misalnya:
[AutoAwait]
public Task<Document> DownloadDocumentAsync()
Kemudian di dalam async
metode apa pun , kompiler akan menganggap Anda ingin menunggu panggilan DownloadDocumentAsync
, jadi Anda tidak perlu menentukannya. Panggilan apa pun ke metode itu akan secara otomatis menunggunya.
Document doc = DownloadDocumentAsync();
Sekarang, jika Anda ingin "menjadi pintar" dan memperoleh Task<Document>
, Anda menggunakan operator start
, yang hanya dapat muncul sebelum pemanggilan metode:
Task<Document> task = start DownloadDocumentAsync();
Rapi, saya pikir. Sekarang pemanggilan metode biasa berarti apa yang biasanya artinya: tunggu sampai metode selesai. Danstart
menunjukkan sesuatu yang berbeda: jangan menunggu.
Untuk kode yang muncul di luar async
metode, satu-satunya cara Anda diizinkan memanggil [AutoAwait]
metode adalah dengan mengawali dengan metode tersebut start
. Ini memaksa Anda untuk menulis kode yang memiliki arti yang sama terlepas dari apakah kode itu muncul dalamasync
metode atau tidak.
Lalu saya mulai menjadi serakah! :)
Pertama, saya ingin async
menerapkan metode antarmuka:
interface IThing
{
async int GetCount();
}
Ini pada dasarnya berarti bahwa metode implementasi harus kembali Task<int>
atau sesuatu yang kompatibel dengan await
, dan penelepon ke metode tersebut akan mendapatkan [AutoAwait]
perilaku.
Juga ketika saya menerapkan metode di atas, saya ingin dapat menulis:
async int GetCount()
Jadi saya tidak perlu menyebutkan Task<int>
sebagai tipe pengembalian.
Juga, saya ingin async
menerapkan tipe delegasi (yang, bagaimanapun juga, seperti antarmuka dengan satu metode). Begitu:
public async delegate TResult AsyncFunc<TResult>();
Seorang async
delegasi memiliki - Anda dapat menebaknya - [AutoAwait]
perilaku. Dari suatu async
metode Anda dapat memanggilnya dan itu akan secara otomatis await
diedit (kecuali jika Anda memilih untuk melakukannya saja start
). Jadi jika Anda mengatakan:
AsyncFunc<Document> getDoc = DownloadDocumentAsync;
Itu hanya berfungsi. Ini bukan panggilan metode. Belum ada tugas yang dimulai - dan async delegate
bukan tugas. Ini pabrik untuk membuat tugas. Anda bisa mengatakan:
Document doc = getDoc();
Dan itu akan memulai tugas dan menunggu sampai selesai dan memberi Anda hasilnya. Atau Anda bisa mengatakan:
Task<Document> t = start getDoc();
Jadi satu tempat di mana "pipa ledeng" bocor adalah bahwa jika Anda ingin membuat delegasi ke suatu async
metode, Anda harus tahu untuk menggunakan suatu async delegate
tipe. Jadi, bukannya Func
Anda harus mengatakanAsyncFunc
, dan seterusnya. Meskipun suatu hari hal semacam itu mungkin diperbaiki oleh inferensi tipe yang ditingkatkan.
Pertanyaan lain adalah apa yang harus terjadi jika Anda mengatakan mulai dengan metode biasa (non-async). Jelas kesalahan kompilasi akan menjadi opsi yang aman. Tetapi ada kemungkinan lain.