Saya memiliki operasi berikut di Web API yang saya buat:
// GET api/<controller>
[HttpGet]
[Route("pharmacies/{pharmacyId}/page/{page}/{filter?}")]
public CartTotalsDTO GetProductsWithHistory(Guid pharmacyId, int page, string filter = null ,[FromUri] bool refresh = false)
{
return delegateHelper.GetProductsWithHistory(CustomerContext.Current.GetContactById(pharmacyId), refresh);
}
Panggilan ke layanan web ini dilakukan melalui panggilan Jquery Ajax dengan cara ini:
$.ajax({
url: "/api/products/pharmacies/<%# Farmacia.PrimaryKeyId.Value.ToString() %>/page/" + vm.currentPage() + "/" + filter,
type: "GET",
dataType: "json",
success: function (result) {
vm.items([]);
var data = result.Products;
vm.totalUnits(result.TotalUnits);
}
});
Saya telah melihat beberapa pengembang yang menerapkan operasi sebelumnya dengan cara ini:
// GET api/<controller>
[HttpGet]
[Route("pharmacies/{pharmacyId}/page/{page}/{filter?}")]
public async Task<CartTotalsDTO> GetProductsWithHistory(Guid pharmacyId, int page, string filter = null ,[FromUri] bool refresh = false)
{
return await Task.Factory.StartNew(() => delegateHelper.GetProductsWithHistory(CustomerContext.Current.GetContactById(pharmacyId), refresh));
}
Namun, harus dikatakan, bahwa GetProductsWithHistory () adalah operasi yang cukup lama. Mengingat masalah dan konteks saya, bagaimana membuat operasi webAPI asynchronous menguntungkan saya?
c#
jquery
ajax
asp.net-web-api
async-await
David Jiménez Martínez
sumber
sumber
async Task<T>
. Ingat, AJAX diimplementasikan bahkan sebelum TPL ada :)GetProductsWithHistoryAsync()
kembaliTask<CartTotalsDTO>
. Ada keuntungan untuk menulis async controller Anda jika Anda bermaksud untuk memigrasi panggilan yang dibuatnya menjadi async juga; kemudian Anda mulai mendapatkan manfaat dari bagian asinkron saat Anda memigrasi sisanya.Jawaban:
Dalam contoh spesifik Anda, operasi tersebut sama sekali tidak asinkron sehingga yang Anda lakukan adalah asinkron melalui sinkronisasi. Anda baru saja melepaskan satu utas dan memblokir utas lainnya. Tidak ada alasan untuk itu, karena semua utas adalah utas kumpulan utas (tidak seperti dalam aplikasi GUI).
Dari Haruskah saya mengekspos pembungkus sinkron untuk metode asinkron?
Namun saat membuat panggilan WebAPI di
async
mana ada operasi asinkron yang sebenarnya (biasanya I / O) alih-alih memblokir utas yang duduk dan menunggu hasil, utas kembali ke kumpulan utas dan dengan demikian dapat melakukan beberapa operasi lain. Secara keseluruhan, itu berarti bahwa aplikasi Anda dapat melakukan lebih banyak hal dengan sumber daya yang lebih sedikit dan meningkatkan skalabilitas.sumber
await Task.Run(() => CPUIntensive())
) tidak berguna di asp.net. Anda tidak mendapatkan apa-apa dari melakukan itu. Anda baru saja melepaskan satu utas ThreadPool untuk menempati utas lainnya. Ini kurang efisien daripada hanya memanggil metode sinkron.await Task.WhenAll
untuk mengeksekusi secara paralel.Task.Run
jika Anda ingin memparalelkan beban Anda pada beberapa utas, tetapi bukan itu yang dimaksud dengan "asinkron melalui sinkronisasi". Referensi "async over sync" membuat metode asinkron sebagai pembungkus di atas metode sinkron. Anda bisa melihat kutipan di jawaban saya.Salah satu pendekatannya adalah (Saya telah berhasil menggunakan ini dalam aplikasi pelanggan) agar Layanan Windows menjalankan operasi yang panjang dengan utas pekerja, dan kemudian melakukan ini di IIS untuk membebaskan utas hingga operasi pemblokiran selesai: Catatan, ini menganggap hasil disimpan dalam tabel (baris diidentifikasi oleh jobId) dan proses pembersihan membersihkannya beberapa jam setelah digunakan.
Untuk menjawab pertanyaan, "Mengingat masalah dan konteks saya, bagaimana membuat operasi webAPI asynchronous menguntungkan saya?" mengingat bahwa ini adalah "operasi yang cukup lama". Saya memikirkan beberapa detik daripada ms, pendekatan ini membebaskan utas IIS. Jelas Anda juga harus menjalankan layanan windows yang dengan sendirinya mengambil sumber daya tetapi pendekatan ini dapat mencegah banjir kueri yang lambat untuk mencuri utas dari bagian lain sistem.
sumber