Apakah System.Timers.Timer berlalu pada utas terpisah dari utas yang membuatnya?
Katakanlah saya memiliki kelas dengan pengatur waktu yang menyala setiap 5 detik. Saat pengatur waktu menyala, dalam metode yang telah berlalu, beberapa objek diubah. Katakanlah butuh waktu lama untuk memodifikasi objek ini, seperti 10 detik. Apakah mungkin saya akan mengalami benturan thread dalam skenario ini?
c#
multithreading
timer
pengguna113164
sumber
sumber
Jawaban:
Untuk System.Timers.Timer :
Lihat jawaban Brian Gideon di bawah ini
Untuk System.Threading.Timer :
Dokumentasi MSDN tentang Pengatur Waktu menyatakan:
Jadi memang pengatur waktu berlalu di utas yang berbeda.
sumber
Tergantung. Ini
System.Timers.Timer
memiliki dua mode operasi.Jika
SynchronizingObject
disetel ke sebuahISynchronizeInvoke
instance, makaElapsed
acara tersebut akan dijalankan di thread yang menghosting objek sinkronisasi. BiasanyaISynchronizeInvoke
contoh ini tidak lain adalah contoh lamaControl
danForm
contoh yang kita semua kenal. Jadi dalam kasus ini,Elapsed
peristiwa dipanggil pada UI thread dan berperilaku mirip denganSystem.Windows.Forms.Timer
. Jika tidak, itu sangat tergantung padaISynchronizeInvoke
contoh spesifik yang digunakan.Jika
SynchronizingObject
null makaElapsed
acara tersebut dipanggil pada aThreadPool
thread dan berperilaku mirip denganSystem.Threading.Timer
. Faktanya, itu benar-benar menggunakan diSystem.Threading.Timer
belakang layar dan melakukan operasi marsaling setelah menerima panggilan balik pengatur waktu jika diperlukan.sumber
System.Threading.Timer
atauSystem.Timers.Timer
?System.Timers.Timer
memiliki dua mode operasi. Ini dapat berjalan pada utas kumpulan utas yang ditetapkan secara acak ATAU dapat berjalan di utas apa pun yang menghostingISynchronizeInvoke
instance. Saya tidak tahu bagaimana membuatnya lebih jelas.System.Threading.Timer
tidak ada hubungannya (jika ada) dengan pertanyaan awal.lock
untuk itu?Setiap peristiwa yang telah berlalu akan diaktifkan di utas yang sama kecuali yang Berlalu sebelumnya masih berjalan.
Jadi itu menangani tabrakan untuk Anda
coba letakkan ini di konsol
Anda akan mendapatkan sesuatu seperti ini
di mana 10 adalah utas panggilan dan 6 dan 12 diaktifkan dari kejadian bg berlalu. Jika Anda menghapus Thread.Sleep (2000); Anda akan mendapatkan sesuatu seperti ini
Karena tidak ada tabrakan.
Tapi ini masih membuatmu bermasalah. jika Anda menjalankan acara setiap 5 detik dan perlu 10 detik untuk mengedit, Anda perlu penguncian untuk melewati beberapa pengeditan.
sumber
timer.Stop()
di awal metode kejadian berlalu dan kemudiantimer.Start()
di akhir metode kejadian berlalu akan menjaga kejadian berlalu dari bertabrakan.Untuk System.Timers.Timer, di utas terpisah, jika SynchronizingObject tidak disetel.
Output Anda akan melihat jika DummyTimer diaktifkan pada interval 5 detik:
Jadi, seperti yang terlihat, OnDummyTimerFired dijalankan pada thread Pekerja.
Tidak, komplikasi lebih lanjut - Jika Anda mengurangi interval menjadi 10 ms,
Ini karena jika eksekusi prev dari OnDummyTimerFired tidak dilakukan saat centang berikutnya diaktifkan, maka .NET akan membuat utas baru untuk melakukan pekerjaan ini.
Lebih rumit lagi, "Kelas System.Timers.Timer menyediakan cara mudah untuk menangani dilema ini — ini memperlihatkan properti SynchronizingObject publik. Menyetel properti ini ke instance Formulir Windows (atau kontrol pada Formulir Windows) akan memastikan bahwa kode dalam penangan kejadian Berlalu Anda berjalan pada utas yang sama dengan tempat pembuatan instance SynchronizingObject. "
http://msdn.microsoft.com/en-us/magazine/cc164015.aspx#S2
sumber
Jika acara yang telah berlalu membutuhkan waktu lebih lama dari intervalnya, itu akan membuat utas lain untuk memunculkan acara yang telah berlalu. Tetapi ada solusi untuk ini
sumber