System.Timers.Timer vs System.Threading.Timer

565

Saya telah memeriksa beberapa timer yang mungkin akhir-akhir ini, dan System.Threading.Timerdan System.Timers.Timerorang-orang yang terlihat perlu bagi saya (karena mereka mendukung pengumpulan benang).

Saya membuat game, dan saya berencana menggunakan semua jenis acara, dengan interval yang berbeda, dll.

Mana yang terbaik?

TheAJ
sumber

Jawaban:

363

Artikel ini menawarkan penjelasan yang cukup komprehensif:

" Membandingkan Kelas Timer di .NET Framework Class Library " - juga tersedia sebagai file .chm

Perbedaan spesifik tampaknya System.Timers.Timeradalah diarahkan pada aplikasi multithreaded dan karenanya aman-benang melalui SynchronizationObjectpropertinya, sedangkan System.Threading.Timerironisnya tidak aman-out-of-the-box.

Saya tidak percaya bahwa ada perbedaan di antara keduanya karena itu berkaitan dengan seberapa kecil interval Anda.

David Andres
sumber
69
Saya pikir kutipan ini mencerahkan: "Tidak seperti System.Windows.Forms.Timer, System.Timers.Timer class akan, secara default, memanggil pengatur waktu acara Anda pada utas pekerja yang diperoleh dari kumpulan utas bahasa yang diperoleh dari kumpulan ulir bahasa umum (CLR) [...] Kelas System.Timers.Timer menyediakan cara mudah untuk menangani dilema ini — ia mengekspos properti SynchronizingObject publik. Mengatur properti ini ke instance Windows Form (atau kontrol pada Windows Form) akan memastikan bahwa kode dalam pengendali aktivitas yang Sudah Berlalu berjalan pada utas yang sama tempat SynchronizingObject digunakan. "
mico
7
Menurut bagian Keselamatan Thread di Threading.Timer's artikel MSDN , itu benar-benar benang-aman ...
Pieter
62
System.Threading.Timer"Ironisnya" tidak seaman System.Threading.Threadbenang dan benang diperoleh melalui kolam. Hanya karena kelas-kelas ini tidak berpegangan tangan Anda dan mengelola penggunaan lockkata kunci itu sendiri tidak berarti kelas-kelas ini tidak threadsafe. Anda mungkin juga mengatakan System.Threading.Threadini bukan threadsafe, karena itu persis sama benar.
Kirk Woll
8
Juga interval System.Timer.Timer hanya bisa Int32 System.Threading.Timer interval bisa hingga Int64
Brent
11
Sangat disayangkan bahwa jawaban yang sangat menyesatkan ini (paling baik) diterima dan sangat dipilih. Satu-satunya pernyataan material dalam jawaban itu sendiri adalah salah. Itu SynchronizingObjecttidak membuat objek timer itu sendiri thread-safe. Itu hanya memastikan bahwa kode Anda untuk menangani event timer dipanggil dalam utas tertentu (jika Anda menyetel properti itu dengan tepat). Objek timer itu sendiri tetap tidak dijamin aman, seperti yang dinyatakan dengan jelas dalam dokumentasi. Di sisi lain, System.Threading.Timerobjek secara khusus didokumentasikan sebagai thread-safe.
Peter Duniho
169

System.Threading.Timeradalah timer biasa. Itu memanggil Anda kembali pada utas pool (dari pool pekerja).

System.Timers.Timeradalah System.ComponentModel.Componentyang membungkus a System.Threading.Timer, dan menyediakan beberapa fitur tambahan yang digunakan untuk pengiriman pada utas tertentu.

System.Windows.Forms.Timeralih-alih membungkus pesan asli -saja-HWND dan menggunakan Window Timers untuk meningkatkan peristiwa dalam loop pesan HWND itu.

Jika aplikasi Anda tidak memiliki UI, dan Anda ingin .Net timer yang paling ringan dan serba guna mungkin, (karena Anda senang mengetahui threading / pengiriman Anda sendiri) maka System.Threading.Timersama baiknya dengan yang ada dalam kerangka kerja.

Saya tidak sepenuhnya jelas apa yang seharusnya 'tidak aman' dengan masalah System.Threading.Timer. Mungkin sama seperti yang ditanyakan dalam pertanyaan ini: Thread-safety System.Timers.Timer vs System.Threading.Timer , atau mungkin semua orang hanya berarti bahwa:

  1. mudah untuk menulis kondisi lomba saat Anda menggunakan timer. Misalnya lihat pertanyaan ini: Pengatur waktu (System.Threading) pengaman ulir

  2. re-entrancy pemberitahuan timer, di mana event timer Anda dapat memicu dan memanggil Anda kembali untuk kedua kalinya sebelum Anda selesai memproses acara pertama . Misalnya lihat pertanyaan ini: Eksekusi aman-thread menggunakan System.Threading.Timer dan Monitor

Tim Lovell-Smith
sumber
Benar System.Timers.Timermenggunakan System.Threading.Timerinternal. Lihat kode sumber .
stomy
120

Dalam bukunya " CLR Via C # ", Jeff Ritcher tidak suka menggunakan System.Timers.Timer, timer ini berasal dari System.ComponentModel.Component, memungkinkan untuk digunakan dalam permukaan desain Visual Studio. Sehingga itu hanya akan berguna jika Anda ingin timer pada permukaan desain.

Dia lebih suka menggunakan System.Threading.Timeruntuk tugas-tugas latar belakang pada thread pool thread.

Pahlawan
sumber
36
Ini dapat digunakan dalam permukaan desain - bukan berarti harus demikian, dan tidak ada efek merugikan jika tidak melakukannya. Membaca artikel di jawaban sebelumnya untuk pertanyaan ini, Timers.Timer tampaknya jauh lebih disukai daripada Threading.Timer.
Stephen Drew
6
Nah, apa yang disukai tergantung pada konteksnya, kan? Seperti yang saya pahami, System.Threading.Timer mengeksekusi callback pass-in pada utas pekerja baru dari ThreadPool. Yang saya anggap juga mengapa itu tidak selalu aman. Agak masuk akal. Jadi, secara teori, Anda tidak perlu khawatir tentang kerja keras memintal thread pekerja Anda sendiri, karena timer ini akan melakukannya untuk Anda. Agaknya sangat berguna.
Finster
6
Menggunakan System.Threading.Timermirip dengan menggunakan kumpulan utas atau membuat utas Anda sendiri. Tentu saja kelas-kelas ini tidak menangani sinkronisasi untuk Anda - itu tugas Anda! Baik thread pool thread, thread Anda sendiri, atau callback timer tidak akan menangani penguncian - pada objek apa dan dalam mode apa dan dalam keadaan apa Anda perlu mengunci membutuhkan penilaian yang baik dan versi threading dari timer memberi Anda fleksibilitas dan rincian
Kirk Woll
2
-1 jawaban ini subyektif atau pendapat dari awal dan tidak menawarkan informasi konkret tentang mengapa System.Threading.Timer lebih disukai oleh Jeff Ritcher
Brian Ogden
42

Informasi dari Microsoft tentang ini (lihat Keterangan di MSDN ):

  • System.Timers.Timer , yang menjalankan suatu peristiwa dan mengeksekusi kode dalam satu atau lebih peristiwa tenggelam secara berkala. Kelas ini dimaksudkan untuk digunakan sebagai komponen berbasis server atau layanan di lingkungan multithreaded; tidak memiliki antarmuka pengguna dan tidak terlihat saat runtime.
  • System.Threading.Timer , yang mengeksekusi metode callback tunggal pada thread pool thread secara berkala. Metode panggilan balik ditentukan saat timer dipakai dan tidak dapat diubah. Seperti kelas System.Timers.Timer, kelas ini dimaksudkan untuk digunakan sebagai komponen berbasis server atau layanan di lingkungan multithreaded; tidak memiliki antarmuka pengguna dan tidak terlihat saat runtime.
  • System.Windows.Forms.Timer (.NET Framework saja), komponen Windows Forms yang menjalankan suatu peristiwa dan mengeksekusi kode dalam satu atau beberapa peristiwa tenggelam secara berkala. Komponen tidak memiliki antarmuka pengguna dan dirancang untuk digunakan dalam lingkungan berulir tunggal; dijalankan pada utas UI.
  • System.Web.UI.Timer (.NET Framework saja), komponen ASP.NET yang melakukan postback halaman web asinkron atau sinkron pada interval reguler.

Sangat menarik untuk menyebutkan bahwa System.Timers.Timersudah usang dengan .NET Core 1.0, tetapi diimplementasikan lagi dalam .NET Core 2.0 (/ .NET Standard 2.0). Tujuan dengan .NET Standard 2.0 adalah semudah mungkin untuk beralih dari .NET Framework yang mungkin merupakan alasan mengapa ia kembali.

Ketika sudah tidak digunakan lagi, .NET Portability Analyzer Visual Studio Add-in direkomendasikan untuk digunakan System.Threading.Timersebagai gantinya.

Sepertinya itu nikmat Microsoft System.Threading.Timersebelumnya System.Timers.Timer.

EDIT NOTE 2018-11-15: Saya ingin mengubah jawaban saya karena informasi lama tentang .NET Core 1.0 sudah tidak berlaku lagi.

ice1e0
sumber
@Taegost, penggunaannya juga terbatas - lihat MSDN msdn.microsoft.com/en-us/library/… dan bacalah pernyataan tentang ketersediaan platform.
astrowalker
@astrowalker - Terima kasih untuk itu, saat saya berkomentar, jawaban ini hampir tidak ada detailnya. Karena sekarang memiliki detail yang saya tanyakan, saya menghapus komentar saya.
Taegost
1
System.Timers.Timer sekarang didukung di .NET Standard 2.0 dan .NET Core 2.0 dan di atasnya. docs.microsoft.com/en-us/dotnet/api/system.timers.timer (gulir ke bagian akhir artikel)
Lee Grissom
Ada juga System.Windows.Threading.DispatcherTimer per jawaban ini .
SpeedCoder5
39

Satu perbedaan penting yang tidak disebutkan di atas yang mungkin membuat Anda keluar adalah System.Timers.Timerdiam - diam menelan pengecualian, sedangkan System.Threading.Timertidak.

Sebagai contoh:

var timer = new System.Timers.Timer { AutoReset = false };
timer.Elapsed += (sender, args) =>
{
    var z = 0;
    var i = 1 / z;
};
timer.Start();

vs.

var timer = new System.Threading.Timer(x =>
{
    var z = 0;
    var i = 1 / z;
}, null, 0, Timeout.Infinite);
stovroz
sumber
1
Saya baru-baru ini membahas masalah ini dengan Timers. Teimer dan sudah sangat menyakitkan ... Ada ide bagaimana saya bisa menulis ulang dengan Threading. Teimer? stackoverflow.com/questions/41618324/…
Tez Wingfield
7
Ada tangkapan kosong di kode sumber. Lihat kode sumber System.Timers.Timer di sini
stomy
Omgsh mengapa programmer MS tidak dapat melakukan hal yang sama benar-benar sama?
xmedeko
2
Contoh tidak menjelaskan bagaimana yang satu menelan pengecualian dan yang lainnya tidak. Bisakah seseorang mengisi rinciannya?
sean
24

Saya menemukan perbandingan singkat dari MSDN

Perpustakaan .NET Framework Class menyertakan empat kelas bernama Timer, yang masing-masing menawarkan fungsionalitas berbeda:

System.Timers.Timer, yang menjalankan suatu peristiwa dan mengeksekusi kode dalam satu atau lebih peristiwa tenggelam secara berkala. Kelas ini dimaksudkan untuk digunakan sebagai komponen berbasis server atau layanan di lingkungan multithreaded; tidak memiliki antarmuka pengguna dan tidak terlihat saat runtime.

System.Threading.Timer, yang mengeksekusi metode panggilan balik tunggal pada utas kumpulan thread secara berkala. Metode panggilan balik ditentukan saat timer dipakai dan tidak dapat diubah. Seperti kelas System.Timers.Timer, kelas ini dimaksudkan untuk digunakan sebagai komponen berbasis server atau layanan di lingkungan multithreaded; tidak memiliki antarmuka pengguna dan tidak terlihat saat runtime.

System.Windows.Forms.Timer, komponen Windows Forms yang menjalankan suatu peristiwa dan mengeksekusi kode dalam satu atau beberapa peristiwa tenggelam secara berkala. Komponen tidak memiliki antarmuka pengguna dan dirancang untuk digunakan dalam lingkungan berulir tunggal.

System.Web.UI.Timer, komponen ASP.NET yang melakukan postback halaman web asinkron atau sinkron secara berkala.

Default
sumber
1

Kedua kelas secara fungsional setara, kecuali yang System.Timers.Timermemiliki opsi untuk memanggil semua panggilan balik kadaluwarsa waktunya melalui ISynchronizeInvoke dengan mengatur SynchronizingObject . Jika tidak, kedua timer akan memanggil callback kadaluarsa pada utas pool thread.

Saat Anda menyeret System.Timers.Timerke permukaan desain Formulir Windows, Visual Studio menetapkan SinkronisasiObjek ke objek formulir, yang menyebabkan semua panggilan balik kedaluwarsa dipanggil pada utas UI.

Edward Brey
sumber
1

Dari MSDN: System.Threading.Timeradalah penghitung waktu yang sederhana dan ringan yang menggunakan metode panggilan balik dan dilayani oleh utas utas. Tidak disarankan untuk digunakan dengan Formulir Windows, karena panggilan baliknya tidak terjadi pada utas antarmuka pengguna. System.Windows.Forms.Timeradalah pilihan yang lebih baik untuk digunakan dengan Formulir Windows. Untuk fungsionalitas penghitung waktu berbasis server, Anda dapat mempertimbangkan untuk menggunakan System.Timers.Timer, yang memunculkan peristiwa dan memiliki fitur tambahan.

Sumber

Greg Gum
sumber