Oba System.Timers.Timer
i System.Threading.Timer
będą działać dla usług.
Zegary, których chcesz unikać, to System.Web.UI.Timer
i System.Windows.Forms.Timer
, które są odpowiednie dla aplikacji ASP i WinForms. Korzystanie z nich spowoduje, że usługa załaduje dodatkowy zestaw, który nie jest tak naprawdę potrzebny dla typu budowanej aplikacji.
Użyj System.Timers.Timer
jak w poniższym przykładzie (upewnij się, że używasz zmiennej poziomu klasy, aby zapobiec zbieraniu elementów bezużytecznych, zgodnie z odpowiedzią Tima Robinsona):
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
...
*/
Jeśli chcesz System.Threading.Timer
, możesz użyć w następujący sposób:
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();
}
}
}
Oba przykłady pochodzą ze stron MSDN.
Nie używaj do tego usługi. Utwórz normalną aplikację i utwórz zaplanowane zadanie, aby ją uruchomić.
Jest to powszechnie stosowana najlepsza praktyka. Jon Galloway się ze mną zgadza. A może jest na odwrót. Tak czy inaczej, faktem jest, że nie jest najlepszym rozwiązaniem tworzenie usługi systemu Windows w celu wykonania sporadycznego zadania uruchamianego z timerem.
źródło
Albo powinno działać OK. W rzeczywistości System.Threading.Timer używa System.Timers.Timer wewnętrznie.
Powiedziawszy to, łatwo jest nadużywać System.Timers.Timer. Jeśli nie przechowujesz gdzieś obiektu Timer w zmiennej, może on zostać usunięty. Jeśli tak się stanie, twój zegar nie będzie już strzelał. Wywołaj metodę Dispose, aby zatrzymać licznik czasu, lub użyj klasy System.Threading.Timer, która jest nieco ładniejszym opakowaniem.
Jakie problemy widziałeś do tej pory?
źródło
System.Timers.Timer
ponieważ nie obsługuje zgłoszonych wyjątków.Zgadzam się z poprzednim komentarzem, że najlepiej byłoby rozważyć inne podejście. Sugerowałbym napisanie aplikacji konsolowej i użycie harmonogramu Windows:
To będzie:
źródło
Jak już wspomniano, oba
System.Threading.Timer
iSystem.Timers.Timer
będą działać. Duża różnica między nimi polega na tym, że drugi jestSystem.Threading.Timer
owijany.W przeszłości sprawiało mi to duże problemy, więc zawsze korzystałem z „System.Threading.Timer” i nadal bardzo dobrze radziłem sobie z wyjątkami.
źródło
Wiem, że ten wątek jest trochę stary, ale przydał się w konkretnym scenariuszu, który miałem i pomyślałem, że warto zauważyć, że istnieje inny powód, dla którego
System.Threading.Timer
może być dobre podejście. Gdy musisz okresowo wykonywać zadanie, które może zająć dużo czasu i chcesz mieć pewność, że cały okres oczekiwania zostanie wykorzystany między zadaniami lub jeśli nie chcesz, aby zadanie było ponownie uruchamiane przed zakończeniem poprzedniego zadania w przypadku, gdy zadanie trwa dłużej niż okres licznika czasu. Możesz użyć następujących:źródło