Saya telah membaca dokumentasi tentang ini dan saya pikir saya mengerti. Sebuah AutoResetEvent
me - reset ketika kode melewati event.WaitOne()
, tetapi ManualResetEvent
tidak.
Apakah ini benar?
c#
.net
multithreading
autoresetevent
manualresetevent
Ben McNiel
sumber
sumber
Jawaban:
Iya. Ini seperti perbedaan antara jalan tol dan pintu. The
ManualResetEvent
adalah pintu, yang perlu ditutup (ulang) secara manual. IniAutoResetEvent
adalah jalan tol, memungkinkan satu mobil lewat dan secara otomatis menutup sebelum mobil berikutnya bisa lewat.sumber
Bayangkan saja yang
AutoResetEvent
dieksekusiWaitOne()
danReset()
sebagai operasi atom tunggal.sumber
Jawaban singkatnya adalah ya. Perbedaan yang paling penting adalah bahwa AutoResetEvent hanya akan mengizinkan satu utas menunggu untuk melanjutkan. ManualResetEvent di sisi lain akan terus membiarkan utas, beberapa bahkan pada saat yang sama, untuk berlanjut sampai Anda menyuruhnya berhenti (Setel ulang).
sumber
Threading dalam C # - E-Book Gratis
ManualResetEvent adalah variasi pada AutoResetEvent. Ini berbeda karena tidak secara otomatis mengatur ulang setelah utas melalui panggilan WaitOne, dan berfungsi seperti gerbang: memanggil Set membuka gerbang, memungkinkan sejumlah utas apa pun yang ditunggu WaitOne di gerbang; panggilan Atur Ulang menutup gerbang, menyebabkan, berpotensi, antrian para pelayan menumpuk hingga pintu berikutnya dibuka.
Seseorang dapat mensimulasikan fungsi ini dengan bidang "gateOpen" boolean (dideklarasikan dengan kata kunci yang mudah menguap) dalam kombinasi dengan "spin-sleeping" - berulang kali memeriksa tanda, dan kemudian tidur untuk waktu yang singkat.
ManualResetEvents kadang-kadang digunakan untuk memberi sinyal bahwa operasi tertentu selesai, atau inisialisasi thread selesai dan siap untuk melakukan pekerjaan.
sumber
Saya membuat contoh sederhana untuk memperjelas pemahaman dari
ManualResetEvent
vsAutoResetEvent
.AutoResetEvent
: mari kita asumsikan Anda memiliki 3 thread pekerja. Jika salah satu utas tersebut akan memanggilWaitOne()
2 utas lainnya, akan menghentikan eksekusi dan menunggu sinyal. Saya berasumsi mereka menggunakanWaitOne()
. Ini seperti; jika saya tidak bekerja, tidak ada yang bekerja. Dalam contoh pertama Anda bisa melihatnyaKetika Anda memanggil
Set()
semua utas akan bekerja dan menunggu sinyal. Setelah 1 detik saya mengirim sinyal kedua dan mereka mengeksekusi dan menunggu (WaitOne()
). Pikirkan orang-orang ini adalah pemain tim sepak bola dan jika satu pemain mengatakan saya akan menunggu sampai manajer memanggil saya, dan yang lain akan menunggu sampai manajer memberitahu mereka untuk melanjutkan (Set()
)Dalam contoh ini Anda dapat dengan jelas melihat bahwa ketika Anda menekannya pertama kali
Set()
akan melepaskan semua utas, lalu setelah 1 detik memberi sinyal semua utas untuk menunggu! Segera setelah Anda mengaturnya lagi terlepas dari apa yang mereka panggilWaitOne()
di dalam, mereka akan tetap berjalan karena Anda harus menelepon secara manualReset()
untuk menghentikan semuanya.Ini lebih tentang hubungan Wasit / Pemain di sana terlepas dari salah satu pemain yang cedera dan menunggu bermain orang lain akan terus bekerja. Jika Wasit mengatakan tunggu (
Reset()
) maka semua pemain akan menunggu sampai sinyal berikutnya.sumber
autoResetEvent.WaitOne()
mirip dengan
sebagai operasi atom
sumber
OK, biasanya bukan praktik yang baik untuk menambahkan 2 jawaban di utas yang sama, tetapi saya tidak ingin mengedit / menghapus jawaban saya sebelumnya, karena dapat membantu dengan cara lain.
Sekarang, saya membuat cuplikan aplikasi konsol yang jauh lebih komprehensif dan mudah dimengerti, di bawah ini.
Cukup jalankan contoh di dua konsol yang berbeda, dan amati perilaku. Anda akan mendapatkan gagasan yang lebih jelas tentang apa yang terjadi di balik layar.
Atur Ulang Manual
Atur Ulang Otomatis Acara
sumber
AutoResetEvent mempertahankan variabel boolean dalam memori. Jika variabel boolean salah maka ia memblokir utas dan jika variabel boolean benar, ia membuka blokir utas.
Ketika kita instantiate objek AutoResetEvent, kita melewatkan nilai default dari nilai boolean di konstruktor. Di bawah ini adalah sintaks instantiate objek AutoResetEvent.
Metode WaitOne
Metode ini memblokir utas saat ini dan menunggu sinyal oleh utas lainnya. Metode WaitOne menempatkan utas saat ini ke status Sleep thread. Metode WaitOne mengembalikan nilai true jika menerima sinyal yang lain mengembalikan false.
Kelebihan kedua metode WaitOne menunggu jumlah detik yang ditentukan. Jika tidak mendapatkan sinyal, teruskan pekerjaannya.
Kami memanggil metode WaitOne dengan melewatkan 2 detik sebagai argumen. Dalam loop sementara, ia menunggu sinyal selama 2 detik kemudian melanjutkan kerjanya. Ketika utas menerima sinyal, WaitOne mengembalikan true dan keluar dari loop dan mencetak "Utas mendapat sinyal".
Atur metode
Metode Set AutoResetEvent mengirim sinyal ke utas menunggu untuk melanjutkan kerjanya. Di bawah ini adalah sintaks memanggil metode Set.
ManualResetEvent mempertahankan variabel boolean dalam memori. Ketika variabel boolean salah maka ia memblokir semua utas dan ketika variabel boolean benar, ia membuka blokir semua utas.
Ketika kami instantiate ManualResetEvent, kami menginisialisasi dengan nilai boolean default.
Dalam kode di atas, kita menginisialisasi ManualResetEvent dengan nilai salah, itu berarti semua utas yang memanggil metode WaitOne akan memblokir sampai beberapa utas memanggil metode Set ().
Jika kita menginisialisasi ManualResetEvent dengan nilai sebenarnya, semua utas yang memanggil metode WaitOne tidak akan diblokir dan bebas untuk melanjutkan lebih jauh.
Metode WaitOne
Metode ini memblokir utas saat ini dan menunggu sinyal oleh utas lainnya. Mengembalikan nilai true jika menerima sinyal yang lain mengembalikan false.
Di bawah ini adalah sintaks memanggil metode WaitOne.
Dalam kelebihan kedua metode WaitOne, kita dapat menentukan interval waktu sampai utas saat ini menunggu sinyal. Jika dalam waktu internal, itu tidak menerima sinyal itu kembali palsu dan masuk ke baris metode berikutnya.
Di bawah ini adalah sintaks memanggil metode WaitOne dengan interval waktu.
Kami telah menetapkan 5 detik ke dalam metode WaitOne. Jika objek manualResetEvent tidak menerima sinyal antara 5 detik, itu menetapkan variabel isSignalled menjadi false.
Setel Metode
Metode ini digunakan untuk mengirim sinyal ke semua utas menunggu. Set () Metode mengatur variabel objek boolean ManualResetEvent menjadi true. Semua utas menunggu tidak diblokir dan melangkah lebih jauh.
Di bawah ini adalah sintaks memanggil metode Set ().
Metode Reset
Setelah kita memanggil metode Set () pada objek ManualResetEvent, booleannya tetap benar. Untuk mereset nilai, kita dapat menggunakan metode Reset (). Metode reset mengubah nilai boolean menjadi false.
Di bawah ini adalah sintaks memanggil metode Reset.
Kita harus segera memanggil metode Reset setelah memanggil metode Set jika kita ingin mengirim sinyal ke utas beberapa kali.
sumber
Iya. Ini benar sekali.
Anda bisa melihat ManualResetEvent sebagai cara untuk menunjukkan status. Sesuatu aktif (Set) atau mati (Reset). Suatu kejadian dengan beberapa durasi. Utas apa pun yang menunggu keadaan itu terjadi dapat dilanjutkan.
AutoResetEvent lebih sebanding dengan sinyal. Indikasi satu tembakan bahwa sesuatu telah terjadi. Suatu kejadian tanpa durasi apa pun. Biasanya tetapi tidak selalu "sesuatu" yang telah terjadi kecil dan perlu ditangani oleh utas tunggal - maka pengaturan ulang otomatis setelah satu utas mengkonsumsi acara tersebut.
sumber
Ya itu betul.
Anda bisa mendapatkan ide dengan menggunakan keduanya.
Jika Anda perlu memberi tahu bahwa Anda telah selesai dengan beberapa pekerjaan dan lainnya (utas) menunggu ini sekarang dapat dilanjutkan, Anda harus menggunakan ManualResetEvent.
Jika Anda perlu memiliki akses eksklusif bersama ke sumber daya apa pun, Anda harus menggunakan AutoResetEvent.
sumber
Jika Anda ingin memahami AutoResetEvent dan ManualResetEvent Anda perlu memahami bukan threading tetapi menyela!
.NET ingin menyulap pemrograman tingkat rendah sejauh mungkin.
Interupsi adalah sesuatu yang digunakan dalam pemrograman tingkat rendah yang sama dengan sinyal yang dari rendah menjadi tinggi (atau sebaliknya). Ketika ini terjadi, program menghentikan eksekusi normal dan memindahkan pointer eksekusi ke fungsi yang menangani acara ini .
Hal pertama yang harus dilakukan ketika interupsi happend adalah mengatur ulang kondisinya, karena perangkat kerasnya bekerja dengan cara ini:
Ini adalah perbedaan antara ManualResetEvent dan AutoResetEvent.
Jika ManualResetEvent terjadi dan saya tidak meresetnya, lain kali itu terjadi saya tidak akan dapat mendengarkannya.
sumber