Saya memiliki beberapa layanan REST async yang tidak saling bergantung. Itu sementara "menunggu" respons dari Service1, saya dapat memanggil Service2, Service3 dan sebagainya.
Misalnya, lihat kode di bawah ini:
var service1Response = await HttpService1Async();
var service2Response = await HttpService2Async();
// Use service1Response and service2Response
Sekarang, service2Response
tidak bergantung pada service1Response
dan mereka dapat diambil secara mandiri. Oleh karena itu, tidak perlu bagi saya untuk menunggu tanggapan dari layanan pertama untuk memanggil layanan kedua.
Saya tidak berpikir saya bisa menggunakan di Parallel.ForEach
sini karena ini bukan operasi terikat CPU.
Untuk memanggil kedua operasi ini secara paralel, dapatkah saya memanggil penggunaan Task.WhenAll
? Satu masalah yang saya lihat Task.WhenAll
adalah tidak mengembalikan hasil. Untuk mengambil hasilnya, bisakah saya menelepon task.Result
setelah menelepon Task.WhenAll
, karena semua tugas sudah selesai dan semua yang saya butuhkan untuk menjemput kami?
Kode sampel:
var task1 = HttpService1Async();
var task2 = HttpService2Async();
await Task.WhenAll(task1, task2)
var result1 = task1.Result;
var result2 = task2.Result;
// Use result1 and result2
Apakah kode ini lebih baik daripada yang pertama dalam hal kinerja? Adakah pendekatan lain yang bisa saya gunakan?
sumber
I do not think I can use Parallel.ForEach here since it is not CPU bound operation
- Saya tidak melihat logika di sana. Konkurensi adalah konkurensi.Parallel.ForEach
akan menelurkan utas baru sedangkanasync await
akan melakukan segalanya pada satu utas.await
) sebelum siap.WhenAll
sebelum saya lakukanResult
dengan gagasan bahwa ia menyelesaikan semua tugas sebelumnya. Hasilnya disebut. Karena, Task.Result memblokir utas panggilan, saya menganggap bahwa jika saya memanggilnya setelah tugas-tugas benar-benar selesai, ia akan segera mengembalikan hasil. Saya ingin memvalidasi pemahaman.Jawaban:
Tapi itu tidak mengembalikan hasil. Mereka semua akan berada dalam array dari tipe yang umum, jadi tidak selalu berguna untuk menggunakan hasil di mana Anda perlu menemukan item dalam array yang sesuai dengan
Task
yang Anda inginkan hasilnya, dan berpotensi melemparkannya ke nya tipe aktual, jadi itu mungkin bukan pendekatan yang paling mudah / paling mudah dibaca dalam konteks ini, tetapi ketika Anda hanya ingin memiliki semua hasil dari setiap tugas, dan tipe umum adalah tipe yang ingin Anda perlakukan, maka itu bagus .Ya, Anda bisa melakukannya. Anda bisa juga
await
mereka (await
akan membuka pengecualian dalam tugas yang salah, sedangkanResult
akan membuang pengecualian agregat, tetapi kalau tidak akan sama).Itu melakukan dua operasi pada saat yang sama, bukan satu dan kemudian yang lain. Apakah itu lebih baik atau lebih buruk tergantung pada apa operasi yang mendasarinya. Jika operasi yang mendasarinya adalah "membaca file dari disk" maka melakukannya secara paralel kemungkinan lebih lambat, karena hanya ada satu kepala disk dan itu hanya dapat berada di satu tempat pada waktu tertentu; itu melompat-lompat di antara dua file akan lebih lambat daripada membaca satu file lalu yang lainnya. Di sisi lain, jika operasi "melakukan beberapa permintaan jaringan" (seperti halnya di sini) maka mereka kemungkinan besar akan lebih cepat (setidaknya hingga sejumlah permintaan bersamaan), karena Anda dapat menunggu respons dari beberapa komputer jaringan lain sama cepatnya ketika ada juga beberapa permintaan jaringan yang tertunda sedang terjadi. Jika Anda ingin tahu apakah itu
Jika tidak penting bagi Anda bahwa Anda tahu semua pengecualian dilemparkan di antara semua operasi yang Anda lakukan secara paralel, bukan hanya yang pertama, Anda dapat dengan mudah
await
melakukan tugas tanpaWhenAll
sama sekali. Satu-satunya hal yangWhenAll
memberi Anda adalah memilikiAggregateException
dengan setiap pengecualian dari setiap tugas yang salah, daripada melempar ketika Anda menekan tugas yang salah pertama. Sesederhana:sumber
Inilah metode ekstensi yang memanfaatkan SemaphoreSlim dan memungkinkan untuk mengatur tingkat paralelisme maksimum
Penggunaan sampel:
sumber
Anda bisa menggunakan
atau
sumber