Adakah yang bisa menjelaskan jika await
danContinueWith
sama atau tidak dalam contoh berikut. Saya mencoba menggunakan TPL untuk pertama kalinya dan telah membaca semua dokumentasi, tetapi tidak mengerti perbedaannya.
Menunggu :
String webText = await getWebPage(uri);
await parseData(webText);
ContinueWith :
Task<String> webText = new Task<String>(() => getWebPage(uri));
Task continue = webText.ContinueWith((task) => parseData(task.Result));
webText.Start();
continue.Wait();
Apakah yang satu lebih disukai daripada yang lain dalam situasi tertentu?
c#
task-parallel-library
task
async-await
Harrison
sumber
sumber
Wait
panggilan pada contoh kedua maka kedua cuplikan tersebut akan (sebagian besar) setara.getWebPage
Metode Anda tidak dapat digunakan di kedua kode. Dalam kode pertama memilikiTask<string>
tipe kembali sedangkan di kode kedua memilikistring
tipe kembali. jadi pada dasarnya kode Anda tidak dapat dikompilasi. - jika tepatnya.Jawaban:
Di kode kedua, Anda secara bersamaan menunggu kelanjutannya selesai. Pada versi pertama, metode akan kembali ke pemanggil segera setelah mencapai
await
ekspresi pertama yang belum selesai.Mereka sangat mirip karena keduanya menjadwalkan kelanjutan, tetapi segera setelah aliran kontrol menjadi sedikit rumit,
await
mengarah ke kode yang jauh lebih sederhana. Selain itu, seperti dicatat oleh Servy dalam komentar, menunggu tugas akan "membuka" agregat pengecualian yang biasanya mengarah pada penanganan kesalahan yang lebih sederhana.await
Penggunaan juga akan secara implisit menjadwalkan kelanjutan dalam konteks panggilan (kecuali Anda menggunakanConfigureAwait
). Tidak ada yang tidak bisa dilakukan "secara manual", tapi jauh lebih mudah melakukannyaawait
.Saya sarankan Anda mencoba menerapkan urutan operasi yang sedikit lebih besar dengan keduanya
await
danTask.ContinueWith
- ini bisa menjadi pembuka mata yang nyata.sumber
await
mengatasi masalahContinueWith
itu.parseData
dijalankan.Berikut urutan cuplikan kode yang baru-baru ini saya gunakan untuk menggambarkan perbedaan dan berbagai masalah menggunakan pemecahan asinkron.
Misalkan Anda memiliki beberapa event handler di aplikasi berbasis GUI yang membutuhkan banyak waktu, sehingga Anda ingin membuatnya asynchronous. Inilah logika sinkron yang Anda mulai:
LoadNextItem mengembalikan sebuah Tugas, yang pada akhirnya akan menghasilkan beberapa hasil yang ingin Anda periksa. Jika hasil saat ini adalah yang Anda cari, perbarui nilai beberapa penghitung di UI, dan kembali dari metode. Jika tidak, Anda terus memproses lebih banyak item dari LoadNextItem.
Ide pertama untuk versi asynchronous: cukup gunakan lanjutan! Dan mari kita abaikan bagian perulangan untuk saat ini. Maksud saya, apa yang mungkin salah?
Hebat, sekarang kami memiliki metode yang tidak memblokir! Itu malah crash. Setiap pembaruan pada kontrol UI harus terjadi pada UI thread, jadi Anda harus memperhitungkannya. Untungnya, ada opsi untuk menentukan bagaimana kelanjutan harus dijadwalkan, dan ada opsi default hanya untuk ini:
Hebat, sekarang kami memiliki metode yang tidak macet! Itu gagal secara diam-diam. Kelanjutan adalah tugas yang terpisah, dengan statusnya tidak terikat dengan tugas sebelumnya. Jadi, meskipun LoadNextItem gagal, pemanggil hanya akan melihat tugas yang telah berhasil diselesaikan. Oke, lalu teruskan pengecualiannya, jika ada:
Hebat, sekarang ini benar-benar berfungsi. Untuk satu item. Sekarang, bagaimana dengan perulangan itu. Ternyata, solusi yang setara dengan logika versi sinkron asli akan terlihat seperti ini:
Atau, alih-alih semua hal di atas, Anda dapat menggunakan asinkron untuk melakukan hal yang sama:
Itu jauh lebih bagus sekarang, bukan?
sumber