2009-09-13 20 views

risposta

315

Questo articolo offre una spiegazione abbastanza completo:

"Comparing the Timer Classes in the .NET Framework Class Library" - disponibile anche as a .chm file

La differenza specifica sembra essere che System.Timers.Timer è orientata verso le applicazioni multithread ed è quindi thread-safe tramite la sua proprietà SynchronizationObject , mentre System.Threading.Timer ironicamente non è sicuro per i thread pronto all'uso.

Non credo che ci sia una differenza tra i due in quanto riguarda quanto piccoli possono essere gli intervalli.

+60

Penso che questo estratto sia illuminante: "A differenza di System.Windows.Forms.Timer, la classe System.Timers.Timer chiamerà, per impostazione predefinita, il gestore di eventi del timer su un thread di lavoro ottenuto dal Common Language Runtime (CLR) pool di thread. [...] La classe System.Timers.Timer fornisce un modo semplice per affrontare questo dilemma: espone una proprietà pubblica SynchronizingObject. Impostare questa proprietà su un'istanza di un Windows Form (o un controllo su un Windows Form) assicurerà che il codice nel gestore eventi Elapsed venga eseguito sullo stesso thread su cui è stato creato l'istanza di SynchronizingObject. " – mico

+7

In base alla sezione sulla sicurezza dei thread in "Threading.Timer" [articolo MSDN] (http://msdn.microsoft.com/en-us/library/system.threading.timer%28v=vs.110%29. aspx), è perfettamente thread-safe ... – Pieter

+51

'System.Threading.Timer' è" ironicamente "non thread-safe come' System.Threading.Thread' e i thread ottenuti attraverso il pool. Solo perché queste classi non ti tengono per mano e gestiscono l'uso della parola chiave 'lock' non significa che queste classi non siano a prova di bug. Si potrebbe anche dire "System.Threading.Thread" non è protetto da thread, perché è esattamente vero. –

110

Nel suo libro "CLR via C#", Jeff Ritcher scoraggia utilizzando System.Timers.Timer, questo timer è derivato da System.ComponentModel.Component, permettendo così di essere utilizzato in un'area di progettazione di Visual Studio. In modo che sarebbe utile solo se si desidera un timer su una superficie di progettazione.

Preferisce utilizzare System.Threading.Timer per attività in background su un thread di thread.

+31

Può essere utilizzato in una superficie di progettazione - non significa che debba essere, e non ci sono effetti dannosi dal non farlo. Leggendo l'articolo nella precedente risposta a questa domanda, Timers.Timer sembra molto più preferibile a Threading.Timer. –

+4

Bene, ciò che è preferibile dipende dal contesto, giusto? A quanto ho capito, System.Threading.Timer esegue il callback passato su un nuovo thread di lavoro da ThreadPool. Il che, presumo, è anche il motivo per cui non è necessariamente thread-safe. Ha un senso. Quindi, in teoria, non dovresti preoccuparti del grugnito di girare il tuo thread di lavoro, dato che questo timer lo farà per te. Sembra abbastanza ridicolo. – Finster

+4

L'uso di 'System.Threading.Timer' è simile all'utilizzo di un pool di thread o alla creazione di una propria discussione. * Di ** corso ** queste classi non gestiscono la sincronizzazione per te * - questo è il tuo lavoro! Né il thread thread thread, il tuo thread, né il callback del timer gestiranno il lock - su quale oggetto e in quale modo e in quali circostanze è necessario bloccare richiede un buon giudizio e la versione thread del timer ti offre la massima flessibilità e granularità. –

127

System.Threading.Timer è un semplice timer. Ti richiama su un thread pool di thread (dal pool di worker).

System.Timers.Timer è un System.ComponentModel.Component che include uno System.Threading.Timer e fornisce alcune funzionalità aggiuntive utilizzate per l'invio su un determinato thread.

System.Windows.Forms.Timer invece esegue il wrapping nativo message-only-HWND e utilizza Window Timers per generare eventi nel ciclo di messaggi di HWND.

Se la vostra applicazione non ha alcuna interfaccia utente, e si desidera che il più leggero e polivalente timer .Net possibile, (perché si è soddisfatti capire il proprio threading/invio), allora System.Threading.Timer è buono come si arriva in il quadro.

Non sono completamente chiaro quali sono i problemi di "non thread safe" con System.Threading.Timer. Forse è solo stessa ha chiesto in questa domanda: Thread-safety of System.Timers.Timer vs System.Threading.Timer, o forse tutti significa proprio questo:

  1. è facile scrivere condizioni di gara quando si utilizza i timer. Per esempio. vedi questa domanda: Timer (System.Threading) thread safety

  2. re-entrancy delle notifiche timer, dove il vostro evento timer può attivare e richiamare una seconda voltaprima di aver finito di elaborare il primo evento . Per esempio.vedi questa domanda: Thread-safe execution using System.Threading.Timer and Monitor

20

ho trovato un breve confronto MSDN

Il Framework .NET include quattro classi denominate Timer, ognuno dei quali offre diverse funzionalità:

System.Timers.Timer , che genera un evento ed esegue il codice in uno o più event sink a intervalli regolari. La classe è destinata a per l'utilizzo come componente basato su server o servizio in un ambiente multithreaded; non ha interfaccia utente e non è visibile in fase di runtime.

System.Threading.Timer, che esegue un singolo metodo di callback su un thread pool di thread a intervalli regolari. Il metodo di callback è definito quando il timer è istanziato e non può essere modificato. Come la classe System.Timers.Timer, questa classe è concepita per essere utilizzata come componente del server o del servizio in un ambiente con multithreading; it non ha interfaccia utente e non è visibile in fase di runtime.

System.Windows.Forms.Timer, un componente Windows Form che genera un evento ed esegue il codice in uno o più sink di evento a intervalli regolari . Il componente non ha un'interfaccia utente ed è progettato per l'uso in un ambiente a thread singolo.

System.Web.UI.Timer, un componente ASP.NET che esegue postback di pagine Web asincrone o sincrone a intervalli regolari.

1

Le due classi sono funzionalmente equivalenti, tranne che System.Timers.Timer ha un'opzione per richiamare tutti i suoi callback timer di scadenza attraverso ISynchronizeInvoke modificando SynchronizingObject. In caso contrario, entrambi i timer richiamano i callback di scadenza sui thread del pool di thread.

Quando si trascina un System.Timers.Timer su una Windows Form di progettazione, Visual Studio imposta SynchronizingObject all'oggetto forma, che fa sì che tutti i callback di scadenza per essere chiamato sul thread dell'interfaccia utente.

1

Da MSDN: System.Threading.Timer è un timer semplice e leggero che utilizza i metodi di callback ed è servito dai thread del pool di thread. Non è consigliato per l'uso con Windows Form, perché i suoi callback non si verificano sul thread dell'interfaccia utente. System.Windows.Forms.Timer è una scelta migliore per l'utilizzo con Windows Form. Per la funzionalità di timer basata su server, potresti prendere in considerazione l'utilizzo di System.Timers.Timer, che genera eventi e presenta funzionalità aggiuntive.

Source

15

Una differenza importante non elencati qui sopra, che potrebbe prendere fuori è che System.Timers.Timer ingoia silenziosamente eccezioni, mentre System.Threading.Timer non lo fa.

Ad esempio:

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); 
+0

Recentemente ho riscontrato questo problema con Timers.Timer ed è stato molto doloroso ... Qualche idea su come Potrei riscrivere con Threading.Timer? http://stackoverflow.com/questions/41618324/windows-service-runs-but-stops-processing-after-two-days –

23

System.Timers.Timer sembra essere deprecato con .NET Core e ASP.NET core. Quindi prova a usare System.Threading.Timer in future app.


EDIT: OK, mi permetta di essere più preciso:

Con il nuovo .NET Framework core, Microsoft interrotto alcune tecnologie di .NET Framework. Per capirlo: .NET Core è un framework totalmente nuovo - riscritto, multipiattaforma, ecc. Non voglio approfondire qui in dettaglio - per favore leggi lo .NET Blog.

Sul blog c'è un buon articolo sul porting su .NET Core che spiega anche le difficoltà che si possono raggiungere. Una parte di questo è usare lo .NET Portability Analyzer Visual Studio Add-In e correggere gli errori che si ottengono.

Per la classe System.Timers.Timer, ha detto, che .NET Framework, versione = v4.6.2 è supportato, ma .NET Core Version = v5.0 e .NETPlatform, Version = v5.0 non è. Modifiche consigliate: Use System.Threading.Timer.

Quindi mi sembra che lo System.Timers.Timer sia andato per .NET Core.

P.S .: Ma potrebbe tornare - Microsoft ha annunciato che desidera apportare alcune modifiche a CoreCLR (il nome del framework che si utilizza per .NET Core) per semplificare lo sforzo di porting.

+1

Sembra sia vero: https://github.com/npgsql/npgsql/issues/471 # issuecomment-94104090 –

+0

@Taegost, il suo uso è anche limitato - vedere MSDN https://msdn.microsoft.com/en-us/library/system.timers.timer(v=vs.110).aspx e leggere il osservazioni sulla disponibilità della piattaforma. – astrowalker

+0

@astrowalker - Grazie per quello, al momento in cui ho fatto il commento questa risposta non aveva quasi nessun dettaglio. Dal momento che ora ha il dettaglio che stavo indagando, ho cancellato il mio commento. – Taegost

Problemi correlati