Saya memiliki objek pengatur waktu. Saya ingin ini dijalankan setiap menit. Secara khusus, itu harus menjalankan OnCallBack
metode dan menjadi tidak aktif saat OnCallBack
metode sedang berjalan. Setelah OnCallBack
metode selesai, itu (a OnCallBack
) memulai ulang pengatur waktu.
Inilah yang saya miliki sekarang:
private static Timer timer;
private static void Main()
{
timer = new Timer(_ => OnCallBack(), null, 0, 1000 * 10); //every 10 seconds
Console.ReadLine();
}
private static void OnCallBack()
{
timer.Change(Timeout.Infinite, Timeout.Infinite); //stops the timer
Thread.Sleep(3000); //doing some long operation
timer.Change(0, 1000 * 10); //restarts the timer
}
Namun, sepertinya itu tidak berhasil. Ini berjalan sangat cepat setiap 3 detik. Bahkan jika menaikkan periode (1000 * 10). Sepertinya itu menutup mata1000 * 10
Apa kesalahan yang telah aku perbuat?
Timer.Change
: "Jika dueTime adalah nol (0), metode callback akan segera dipanggil.". Sepertinya itu nol bagi saya.Jawaban:
Ini bukan penggunaan yang benar dari System.Threading.Timer. Saat Anda memberi contoh Timer, Anda hampir selalu harus melakukan hal berikut:
Ini akan menginstruksikan pengatur waktu untuk berdetak hanya sekali ketika jeda telah berlalu. Kemudian dalam fungsi Callback Anda mengubah timer setelah pekerjaan selesai, bukan sebelumnya. Contoh:
Jadi tidak perlu mekanisme penguncian karena tidak ada konkurensi. Pengatur waktu akan mengaktifkan panggilan balik berikutnya setelah interval berikutnya telah berlalu + waktu operasi yang berjalan lama.
Jika Anda perlu menjalankan pengatur waktu tepat pada N milidetik, saya sarankan Anda mengukur waktu dari operasi yang berjalan lama menggunakan Stopwatch dan kemudian memanggil metode Ubah dengan tepat:
Saya sangat menganjurkan siapa pun yang melakukan .NET dan menggunakan CLR yang belum membaca buku Jeffrey Richter - CLR via C # , untuk membaca secepat mungkin. Pengatur waktu dan kumpulan benang dijelaskan dengan sangat rinci di sana.
sumber
private void Callback( Object state ) { // Long running operation _timer.Change( TIME_INTERVAL_IN_MILLISECONDS, Timeout.Infinite ); }
.Callback
mungkin dipanggil lagi sebelum operasi selesai.Long running operation
mungkin membutuhkan lebih banyak waktuTIME_INTERVAL_IN_MILLISECONDS
. Lalu apa yang akan terjadi?ThreadPool
, jika Anda memasukkan timer? Saya memikirkan skenario di mana utas baru muncul untuk melakukan pekerjaan pada interval tertentu - dan kemudian diturunkan ke kumpulan utas setelah selesai.Tidak perlu menghentikan timer, lihat solusi bagus dari posting ini :
"Anda dapat membiarkan pengatur waktu terus mengaktifkan metode panggilan balik tetapi membungkus kode non-reentrant Anda di Monitor.TryEnter / Exit. Tidak perlu menghentikan / memulai ulang pengatur waktu dalam hal itu; panggilan yang tumpang tindih tidak akan mendapatkan kunci dan segera kembali."
sumber
Apakah menggunakan
System.Threading.Timer
wajib?Jika tidak,
System.Timers.Timer
memiliki handyStart()
danStop()
metode (danAutoReset
properti yang dapat Anda setel ke false, sehinggaStop()
tidak diperlukan dan Anda cukup memanggilStart()
setelah menjalankan).sumber
Saya hanya akan melakukan:
Dan abaikan parameter periode, karena Anda mencoba untuk mengontrol periodicy sendiri.
Kode asli Anda berjalan secepat mungkin, karena Anda tetap menentukan
0
untukdueTime
parameter. DariTimer.Change
:sumber
Change()
metode?jika Anda suka menggunakan beberapa utas lingkaran di dalam ...
sumber