async + menunggu == sinkronkan?

24

Tersandung pada posting ini yang berbicara tentang membuat permintaan web async.

Selain kesederhanaan, jika di dunia nyata, yang Anda lakukan hanyalah membuat permintaan async dan menunggu di baris berikutnya, bukankah itu sama dengan membuat panggilan sinkronisasi di tempat pertama?

Tuan
sumber
5
Tidak persis. Kode Anda sinkron dalam arti tidak ada yang terjadi sampai Anda mendapatkan hasil. Namun di bawahnya, Anda mungkin menyerah utas yang sedang Anda jalankan sampai metode async kembali, lalu mendapat utas lain untuk melanjutkan eksekusi.
R0MANARMY
2
tetapi dengan async Anda dapat melakukan async lain pada saat yang sama dan kemudian menunggu 2, dengan sinkronisasi ini tidak mungkin
ratchet freak
Berikut ini adalah artikel ( tomasp.net/blog/async-compilation-internals.aspx ) yang membahas beberapa di bawah kap async di C # - ini adalah bagian dari seri yang mencakup pemrograman asinkron dalam C # dan F #.
paul
@ scratchetfreak: Ya, tidak perlu dikatakan lagi jika Anda melakukan banyak panggilan.
Mrchief
@ R0MANARMY: Jika aplikasi Anda melakukan hal-hal lain, maka ya dan async + menunggu memungkinkan itu. Akim mengatakan yang terbaik! Tapi bayangkan kode tidak ada di button_click handler, atau event handler semacam itu. Jika seseorang secara buta menyalin kode (async + menunggu baris), ke metode apa pun, itu dapat menyebabkan kesan palsu bahwa kode Anda async tetapi yang berlaku mungkin tidak.
Mrchief

Jawaban:

32

Tidak, async + await != synckarena kelanjutan

Dari MSDN 'Pemrograman Asinkron dengan Async dan Menunggu (C # dan Visual Basic)'

Metode Async dimaksudkan sebagai operasi non-pemblokiran. Ekspresi menunggu dalam metode async tidak memblokir utas saat ini sementara tugas yang ditunggu-tunggu sedang berjalan. Sebaliknya, ekspresi mendaftar sisa metode sebagai kelanjutan dan mengembalikan kontrol ke pemanggil metode async .

Misalnya eksekusi async tidak akan memblokir utas UI, dan Some TextBox.Textakan diperbarui setelah unduhan selesai

private async void OnButtonClick()
{
   SomeTextBox.Text = await new WebClient().DownloadStringTaskAsync("http://stackoverflow.com/");
}
Akim
sumber
Sangat baik dikatakan!
Mrchief
Bisakah Anda jelaskan lebih detail. Apakah Anda mengatakan ... bahwa tanpa ini ... Anda tidak akan dapat berinteraksi dengan UI ... karena ini akan berada di utas utama. Jadi apakah ini berarti bahwa ini hanya berlaku dalam program jenis aplikasi yang ditujukan ke web di mana interaksi terpisah dari utas server web. Jadi di shell kacang ini hanya menjadi penting yaitu tidak disinkronkan * ketika utas utama Anda adalah utas berjalan. Bukankah ini akan membuat perilaku yang tidak terduga, yaitu di App (1 utas utama) dua tombol diklik .. tetapi Anda harus dapat mengklik 1 tanpa menyelesaikan pertama?
Seabizkit
Bagaimana dengan Console.WriteLine(await GetStringOverNetwork());? Bagaimana jika Anda memerlukan output dari doa asinkron? Apakah program akan memblokir akses pertama, bahkan jika utas berpotensi melanjutkan eksekusi?
Andrew
6

Tidak, itu tidak sama.

asyncBlok kode Anda sedang menunggu awaitpanggilan kembali untuk melanjutkan, namun aplikasi Anda yang lain tidak menunggu dan masih dapat berlanjut seperti biasa.

Sebaliknya, panggilan sinkron akan membuat seluruh aplikasi atau utas Anda menunggu hingga kode selesai dijalankan untuk melanjutkan dengan hal lain.

Rachel
sumber
tidak bisakah panggilan sinkronisasi diimplementasikan sebagai async + menunggu?
ratchet freak
@ scratchetfreak Saya pikir ada beberapa overhead untuk menyiapkan menunggu / async, jadi saya tidak berpikir Anda ingin kode seluruh aplikasi Anda dengan itu. Saya hanya menggunakannya untuk mengeksekusi blok kode yang berpotensi berjalan lama sehingga tidak mengunci aplikasi saya. :)
Rachel
5

Ijinkan saya untuk mengklarifikasi hal-hal yang berkaitan dengan async / menunggu.

Ketika menunggu ditemui mesin negara yang mendasari memungkinkan kontrol untuk segera dikembalikan. Kemudian, ketika panggilan yang ditunggu selesai, mesin negara yang mendasari memungkinkan eksekusi untuk melanjutkan di garis setelah panggilan yang ditunggu.

Oleh karena itu, blok async tidak diblokir juga tidak menunggu panggilan yang ditunggu selesai; Kontrol dikembalikan segera ketika perintah tunggu ditemui.

Mesin negara yang mendasarinya adalah bagian dari "sihir" di balik penggunaan async / menunggu yang tidak digunakan dan dilewatkan.

Cedric Harris
sumber
2

Saya tersandung pada ini dengan pertanyaan yang sama dalam pikiran, namun setelah membaca tanggapan pertanyaan itu tampaknya berlama-lama, bingung dengan referensi untuk "sihir di bawah tenda".

Dari Pemrograman Asinkron yang disebutkan di atas :

  • Kata asynckunci mengubah metode menjadi metode async, yang memungkinkan Anda untuk menggunakan awaitkata kunci dalam tubuhnya.
  • Ketika awaitkata kunci diterapkan, itu menangguhkan metode panggilan dan menghasilkan kontrol kembali ke pemanggilnya sampai tugas yang ditunggu selesai.
  • awaithanya dapat digunakan di dalam suatu asyncmetode.

Apakah konteks yang ditemui awaitdiblokir?

  • Ya . Pada dasarnya itu adalah penghalang sinkronisasi lokal untuk mempertahankan status yang diketahui dalam konteks eksekusi; kecuali bahwa konteks lain, jika ada, tidak bergabung.

Apakah sisa blok aplikasi di await?

  • Itu tergantung pada bagaimana aplikasi Anda ditulis. Jika itu adalah serangkaian awaittugas ed dependen yang diluncurkan secara berurutan dalam konteks yang sama (lihat: Mencoba memahami perilaku asinkron / menunggu )

    await asyncCall1();
    await asyncCall2();  // waits for asyncCall1() to complete
    

    dengan cara ini masing await- masing akan memblokir pemijahan yang berikutnya.

    Di sisi lain, tugas dependen yang sama yang diluncurkan secara paralel akan dieksekusi secara paralel dan konteksnya hanya akan memblokir pada resp. await:

    Task<int> t1 = asyncCall1();
    Task<string> t2 = asyncCall2();  // runs in parallel with asyncCall1()
    int val = await t1;
    string str = await t2;  // waits for asyncCall1() to complete
    

    Secara umum, awaithasil eksekusi ke konteks luar, dari mana konteks saat ini dipanggil. Namun, jika konteks luar itu sendiri sedang menunggu arus, maka itu seperti urutan berurutan awaitdalam konteks yang sama.

Jadi, untuk menuai asyncmanfaatnya, seseorang perlu merancang aplikasi untuk menjalankan beberapa konteks paralel (UI, data-klien dll), kemudian awaitdalam satu konteks menghasilkan eksekusi ke konteks lain, sehingga seluruh aplikasi tidak akan menghalangi individu await.

oversynched
sumber