Ini kode yang saya miliki tetapi saya tidak mengerti apa SemaphoreSlim
yang saya lakukan.
async Task WorkerMainAsync()
{
SemaphoreSlim ss = new SemaphoreSlim(10);
List<Task> trackedTasks = new List<Task>();
while (DoMore())
{
await ss.WaitAsync();
trackedTasks.Add(Task.Run(() =>
{
DoPollingThenWorkAsync();
ss.Release();
}));
}
await Task.WhenAll(trackedTasks);
}
void DoPollingThenWorkAsync()
{
var msg = Poll();
if (msg != null)
{
Thread.Sleep(2000); // process the long running CPU-bound job
}
}
Apa yang menunggu ss.WaitAsync();
dan ss.Release();
dilakukan?
Saya kira jika saya menjalankan 50 utas sekaligus kemudian menulis kode seperti SemaphoreSlim ss = new SemaphoreSlim(10);
itu maka itu akan dipaksa untuk menjalankan 10 utas aktif sekaligus.
Ketika salah satu dari 10 utas selesai, utas lainnya akan dimulai. Jika saya tidak benar, bantu saya untuk memahami dengan situasi sampel.
Mengapa await
dibutuhkan bersama ss.WaitAsync();
? Apa yang ss.WaitAsync();
dilakukannya?
Jawaban:
Itu betul; penggunaan semaphore memastikan bahwa tidak akan ada lebih dari 10 pekerja yang melakukan pekerjaan ini pada waktu yang sama.
Memanggil
WaitAsync
di semaphore menghasilkan tugas yang akan diselesaikan ketika utas itu telah diberi "akses" ke token itu.await
-ing tugas itu memungkinkan program melanjutkan eksekusi ketika "diizinkan" untuk melakukannya. Memiliki versi asinkron, daripada memanggilWait
, penting untuk memastikan bahwa metode tetap asinkron, bukan sinkron, serta berkaitan dengan fakta bahwa suatuasync
metode dapat mengeksekusi kode di beberapa utas, karena callback, dan sebagainya. hubungan benang alami dengan semaphore bisa menjadi masalah.Catatan tambahan:
DoPollingThenWorkAsync
tidak boleh memilikiAsync
postfix karena sebenarnya tidak asinkron, melainkan sinkron. Sebut sajaDoPollingThenWork
. Ini akan mengurangi kebingungan bagi para pembaca.sumber
Thread.Sleep
kode asli akan merusak penjadwal tugas. Jika Anda tidak asinkron dengan intinya, Anda tidak asinkron.Di taman kanak-kanak di sudut, mereka menggunakan SemaphoreSlim untuk mengontrol berapa banyak anak yang dapat bermain di ruang olahraga.
Mereka mengecat di lantai, di luar ruangan, 5 pasang tapak kaki.
Saat anak-anak tiba, mereka meninggalkan sepatu dengan sepasang jejak kaki gratis dan memasuki ruangan.
Setelah mereka selesai bermain, mereka keluar, mengambil sepatu mereka dan "melepaskan" slot untuk anak lain.
Jika seorang anak datang dan tidak ada jejak kaki yang tersisa, mereka pergi bermain di tempat lain atau hanya tinggal sebentar dan memeriksa sesekali (mis., Tidak ada prioritas FIFO).
Ketika seorang guru ada di sekitar, dia "melepaskan" satu baris tambahan 5 jejak kaki di sisi lain koridor sehingga 5 anak lagi dapat bermain di ruangan itu pada waktu yang sama.
Ia juga memiliki "perangkap" yang sama dari SemaphoreSlim ...
Jika seorang anak selesai bermain dan meninggalkan ruangan tanpa mengambil sepatu (tidak memicu "pelepasan") maka slot tetap terhalang, meskipun secara teori ada slot kosong. Namun, anak itu biasanya dimarahi.
Kadang-kadang satu atau dua anak licik menyembunyikan sepatu mereka di tempat lain dan memasuki ruangan, bahkan jika semua jejak kaki sudah diambil (misalnya, SemaphoreSlim tidak "benar-benar" mengontrol berapa banyak anak di ruangan itu).
Ini biasanya tidak berakhir dengan baik, karena kepadatan ruangan cenderung berakhir dengan tangisan anak-anak dan guru menutup ruangan sepenuhnya.
sumber
Meskipun saya menerima pertanyaan ini benar-benar terkait dengan skenario kunci hitung mundur, saya pikir ada baiknya membagikan tautan ini yang saya temukan bagi mereka yang ingin menggunakan SemaphoreSlim sebagai kunci asinkron sederhana. Ini memungkinkan Anda untuk menggunakan pernyataan using yang dapat membuat pengkodean lebih rapi dan aman.
http://www.tomdupont.net/2016/03/how-to-release-semaphore-with-using.html
Saya melakukan swap
_isDisposed=true
dan_semaphore.Release()
berkeliling di Buangnya meskipun jika itu entah bagaimana dipanggil beberapa kali.Juga penting untuk dicatat SemaphoreSlim bukan kunci reentrant, artinya jika utas yang sama memanggil WaitAsync beberapa kali, jumlah semaphore berkurang setiap waktu. Singkatnya, SemaphoreSlim tidak menyadari Thread.
Mengenai kualitas kode pertanyaan, lebih baik meletakkan Rilis di akhir percobaan-akhirnya untuk memastikannya selalu dirilis.
sumber