Beides System.Timers.Timer
und System.Threading.Timer
wird für Dienstleistungen arbeiten.
Die Timer, die Sie vermeiden möchten, sind System.Web.UI.Timer
und System.Windows.Forms.Timer
, die jeweils für ASP-Anwendungen und WinForms gelten. Wenn Sie diese verwenden, lädt der Dienst eine zusätzliche Assembly, die für den von Ihnen erstellten Anwendungstyp nicht wirklich benötigt wird.
Verwenden Sie diese Option System.Timers.Timer
wie im folgenden Beispiel (stellen Sie außerdem sicher, dass Sie eine Variable auf Klassenebene verwenden, um die Speicherbereinigung zu verhindern, wie in der Antwort von Tim Robinson angegeben):
using System;
using System.Timers;
public class Timer1
{
private static System.Timers.Timer aTimer;
public static void Main()
{
// Normally, the timer is declared at the class level,
// so that it stays in scope as long as it is needed.
// If the timer is declared in a long-running method,
// KeepAlive must be used to prevent the JIT compiler
// from allowing aggressive garbage collection to occur
// before the method ends. (See end of method.)
//System.Timers.Timer aTimer;
// Create a timer with a ten second interval.
aTimer = new System.Timers.Timer(10000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
// Set the Interval to 2 seconds (2000 milliseconds).
aTimer.Interval = 2000;
aTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program.");
Console.ReadLine();
// If the timer is declared in a long-running method, use
// KeepAlive to prevent garbage collection from occurring
// before the method ends.
//GC.KeepAlive(aTimer);
}
// Specify what you want to happen when the Elapsed event is
// raised.
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
}
}
/* This code example produces output similar to the following:
Press the Enter key to exit the program.
The Elapsed event was raised at 5/20/2007 8:42:27 PM
The Elapsed event was raised at 5/20/2007 8:42:29 PM
The Elapsed event was raised at 5/20/2007 8:42:31 PM
...
*/
Wenn Sie möchten System.Threading.Timer
, können Sie Folgendes verwenden:
using System;
using System.Threading;
class TimerExample
{
static void Main()
{
AutoResetEvent autoEvent = new AutoResetEvent(false);
StatusChecker statusChecker = new StatusChecker(10);
// Create the delegate that invokes methods for the timer.
TimerCallback timerDelegate =
new TimerCallback(statusChecker.CheckStatus);
// Create a timer that signals the delegate to invoke
// CheckStatus after one second, and every 1/4 second
// thereafter.
Console.WriteLine("{0} Creating timer.\n",
DateTime.Now.ToString("h:mm:ss.fff"));
Timer stateTimer =
new Timer(timerDelegate, autoEvent, 1000, 250);
// When autoEvent signals, change the period to every
// 1/2 second.
autoEvent.WaitOne(5000, false);
stateTimer.Change(0, 500);
Console.WriteLine("\nChanging period.\n");
// When autoEvent signals the second time, dispose of
// the timer.
autoEvent.WaitOne(5000, false);
stateTimer.Dispose();
Console.WriteLine("\nDestroying timer.");
}
}
class StatusChecker
{
int invokeCount, maxCount;
public StatusChecker(int count)
{
invokeCount = 0;
maxCount = count;
}
// This method is called by the timer delegate.
public void CheckStatus(Object stateInfo)
{
AutoResetEvent autoEvent = (AutoResetEvent)stateInfo;
Console.WriteLine("{0} Checking status {1,2}.",
DateTime.Now.ToString("h:mm:ss.fff"),
(++invokeCount).ToString());
if(invokeCount == maxCount)
{
// Reset the counter and signal Main.
invokeCount = 0;
autoEvent.Set();
}
}
}
Beide Beispiele stammen von den MSDN-Seiten.
Verwenden Sie hierfür keinen Dienst. Erstellen Sie eine normale Anwendung und erstellen Sie eine geplante Aufgabe, um sie auszuführen.
Dies ist die gängige Best Practice. Jon Galloway stimmt mir zu. Oder vielleicht ist es umgekehrt. In beiden Fällen ist es nicht empfehlenswert, einen Windows-Dienst zu erstellen, um eine intermittierende Aufgabe auszuführen, die von einem Timer ausgeführt wird.
quelle
Entweder sollte man OK arbeiten. Tatsächlich verwendet System.Threading.Timer intern System.Timers.Timer.
Trotzdem ist es leicht, System.Timers.Timer zu missbrauchen. Wenn Sie das Timer-Objekt nicht irgendwo in einer Variablen speichern, wird möglicherweise Müll gesammelt. In diesem Fall wird Ihr Timer nicht mehr ausgelöst. Rufen Sie die Dispose-Methode auf, um den Timer zu stoppen, oder verwenden Sie die System.Threading.Timer-Klasse, die ein etwas besserer Wrapper ist.
Welche Probleme haben Sie bisher gesehen?
quelle
System.Timers.Timer
weil sie die damit verbundenen Ausnahmen nicht verarbeiten.Ich stimme dem vorherigen Kommentar zu, der am besten geeignet ist, einen anderen Ansatz in Betracht zu ziehen. Mein Vorschlag wäre, eine Konsolenanwendung zu schreiben und den Windows-Scheduler zu verwenden:
Dieser Wille:
quelle
Wie schon gesagt beides
System.Threading.Timer
undSystem.Timers.Timer
wird funktionieren. Der große Unterschied zwischen den beiden besteht darin, dassSystem.Threading.Timer
es sich um einen Wrapper um den anderen handelt.Dies gab mir in der Vergangenheit große Probleme, so dass ich immer 'System.Threading.Timer' verwendete und Ihre Ausnahmen immer noch sehr gut handhabte.
quelle
Ich weiß, dass dieser Thread ein wenig alt ist, aber er hat sich für ein bestimmtes Szenario als nützlich erwiesen, und ich dachte, es lohnt sich zu bemerken, dass es einen weiteren Grund gibt, warum
System.Threading.Timer
ein guter Ansatz sein könnte. Wenn Sie einen Job regelmäßig ausführen müssen, was lange dauern kann, und Sie sicherstellen möchten, dass die gesamte Wartezeit zwischen den Jobs verwendet wird, oder wenn Sie nicht möchten, dass der Job erneut ausgeführt wird, bevor der vorherige Job abgeschlossen ist, falls Der Job dauert länger als der Timer-Zeitraum. Sie könnten Folgendes verwenden:quelle