Pertanyaan Apakah kata kunci baru C # 5.0 'async' dan 'wait' menggunakan banyak core?


Dua kata kunci baru ditambahkan ke bahasa C # 5.0 async dan menunggu, keduanya bekerja bergandengan tangan untuk menjalankan metode C # secara asinkron tanpa memblokir utas panggilan.

Pertanyaan saya adalah, apakah metode ini benar-benar memanfaatkan beberapa core dan berjalan secara paralel atau apakah metode async berjalan di inti thread yang sama sebagai pemanggil?


57
2018-03-27 22:08


asal


Jawaban:


Dua kata kunci baru ditambahkan ke bahasa C # 5.0 adalah async dan menunggu, keduanya bekerja bergandengan tangan untuk menjalankan metode C # secara asinkron tanpa memblokir utas panggilan.

Itu melintasi tujuan fitur, tetapi memberikan terlalu banyak "kredit" ke async / menunggu fitur.

Biarkan saya sangat, sangat jelas tentang hal ini: await tidak secara ajaib menyebabkan metode sinkron berjalan secara asynchronous. Itu tidak memulai thread baru dan menjalankan metode pada thread baru, misalnya. Metode yang Anda panggil harus menjadi hal yang tahu cara menjalankan dirinya secara asynchronous. Cara memilih untuk melakukannya adalah bisnisnya.

Pertanyaan saya adalah, apakah metode ini benar-benar memanfaatkan beberapa core dan berjalan secara paralel atau apakah metode async berjalan di inti thread yang sama sebagai pemanggil?

Sekali lagi, itu sepenuhnya tergantung pada metode yang Anda panggil. Semua itu await Apakah menginstruksikan compiler untuk menulis ulang metode menjadi delegasi yang dapat dilewati sebagai kelanjutan dari tugas asynchronous. Itu adalah await FooAsync() berarti "panggilan FooAsync() dan apa pun yang datang kembali haruslah sesuatu yang mewakili operasi asynchronous yang baru saja dimulai. Katakan hal itu bahwa ketika tahu bahwa operasi asynchronous dilakukan, ia harus memanggil delegasi ini. "Delegasi memiliki properti yang ketika dipanggil, metode saat ini muncul untuk melanjutkan" di mana ia tinggalkan ".

Jika metode yang Anda panggil jadwal bekerja ke untaian lain yang terkait dengan inti lain, bagus. Jika memulai pengatur waktu yang mengadu beberapa pengendali event di masa depan pada utas UI, bagus. await tidak peduli. Semua yang dilakukannya adalah memastikan bahwa ketika pekerjaan asynchronous selesai, kontrol dapat dilanjutkan di mana ia ditinggalkan.

Sebuah pertanyaan yang Anda tidak tanyakan tetapi mungkin seharusnya adalah:

Ketika tugas asynchronous selesai dan kontrol mengambil tempat yang tersisa, apakah eksekusi di thread yang sama seperti sebelumnya?

Itu tergantung pada konteksnya. Dalam aplikasi winforms di mana Anda menunggu sesuatu dari utas UI, kontrol mengambil lagi di utas UI. Dalam aplikasi konsol, mungkin tidak.


93
2018-03-27 23:05



Eric Lippert memiliki jawaban yang luar biasa; Saya hanya ingin menjelaskan async paralelisme sedikit lebih jauh.

Pendekatan "serial" sederhana adalah di mana Anda await hanya satu hal pada satu waktu:

static void Process()
{
  Thread.Sleep(100); // Do CPU work.
}

static async Task Test()
{
  await Task.Run(Process);
  await Task.Run(Process);
}

Dalam contoh ini, Test metode akan antri Process ke rangkaian utas, dan ketika selesai, itu akan antri Process lagi ke kolam ulir. Itu Test metode akan selesai setelah ~ 200ms. Kapanpun, hanya satu utas yang benar-benar menggerakkan kemajuan ke depan.

Cara sederhana untuk memparalelkan ini adalah dengan menggunakan Task.WhenAll:

static void Process()
{
  Thread.Sleep(100); // Do CPU work.
}

static async Task Test()
{
  // Start two background operations.
  Task task1 = Task.Run(Process);
  Task task2 = Task.Run(Process);

  // Wait for them both to complete.
  await Task.WhenAll(task1, task2);
}

Dalam contoh ini, Test metode antrian Process ke kolam thread dua kali, dan kemudian menunggu mereka menyelesaikan keduanya. Itu Testmetode akan selesai setelah ~ 100ms.

Task.WhenAll (dan Task.WhenAny) diperkenalkan dengan async/await untuk mendukung paralelisme sederhana. Namun, TPL masih ada jika Anda memerlukan sesuatu yang lebih canggih (pemrosesan paralel CPU-terikat yang benar adalah lebih cocok untuk TPL). TPL bermain baik dengan async/await.

Saya meliput dasar async paralelisme dalam diri saya Di toto async posting blog, serta "konteks" yang disinggung Eric.


65
2018-03-28 00:13



Metode async mengembalikan objek yang dapat ditunda (yang memiliki GetAwaiter metode), dan compiler dapat menghasilkan kode untuk mengkonsumsi objek itu jika Anda memanggil metode dengan await kata kunci. Anda juga bebas untuk memanggil metode semacam itu tanpa menunggu kata kunci, dan mengkonsumsi objek secara eksplisit.

Objek mengenkapsulasi aksi asynchronous, yang mungkin atau mungkin tidak berjalan di thread lain. Artikel Eric Lippert Asynchrony in C # 5.0 part Four: Ini bukan sulap menganggap contoh pemrograman asynchronous yang hanya melibatkan satu thread.


4
2018-03-27 22:34



Sejak async dan await didasarkan sekitar TPL, mereka harus bekerja sangat mirip. Secara default, Anda harus memperlakukannya seolah-olah berjalan pada utas yang terpisah.


2
2018-03-27 22:22