Windows 서비스에서 사용하기위한 최상의 타이머
N 기간마다 실행될 Windows 서비스를 만들어야합니다.
질문 :
어떤 타이머 컨트롤을 사용해야합니까 : System.Timers.Timer
나 System.Threading.Timer
하나? 무언가에 영향을 줍니까?
System.Timers.Timer
Windows 서비스에서 제대로 작동하지 않는다는 많은 증거를 들었 기 때문에 묻습니다 .
감사합니다.
두 System.Timers.Timer
및 System.Threading.Timer
서비스에 대해 작동합니다.
피하고자하는 타이머는 System.Web.UI.Timer
및 System.Windows.Forms.Timer
ASP이며 각각 ASP 응용 프로그램과 WinForms에 사용됩니다. 이를 사용하면 서비스에서 추가 어셈블리를로드하게되므로 실제로 구축하려는 응용 프로그램 유형에 필요하지 않습니다.
System.Timers.Timer
다음 예제와 같이 사용하십시오 (또한 Tim Robinson의 답변에 설명 된대로 가비지 콜렉션을 방지하기 위해 클래스 레벨 변수를 사용해야합니다).
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
...
*/
을 선택 System.Threading.Timer
하면 다음과 같이 사용할 수 있습니다.
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();
}
}
}
두 예제 모두 MSDN 페이지에서 제공됩니다.
이를 위해 서비스를 사용하지 마십시오. 일반 애플리케이션을 작성하고 스케줄 된 태스크를 작성하여 실행하십시오.
이것은 일반적으로 유지되는 모범 사례입니다. Jon Galloway가 동의합니다. 아니면 어쩌면 그 반대 일 수도 있습니다. 어느 쪽이든, 사실 타이머를 사용하여 간헐적 인 작업을 수행하기 위해 Windows 서비스를 만드는 것이 가장 좋은 방법은 아닙니다.
"타이머를 실행하는 Windows 서비스를 작성하는 경우 솔루션을 다시 평가해야합니다."
–Jon Galloway, ASP.NET MVC 커뮤니티 프로그램 관리자, 작가, 아르바이트 슈퍼 히어로
Either one should work OK. In fact, System.Threading.Timer uses System.Timers.Timer internally.
Having said that, it's easy to misuse System.Timers.Timer. If you don't store the Timer object in a variable somewhere, then it is liable to be garbage collected. If that happens, your timer will no longer fire. Call the Dispose method to stop the timer, or use the System.Threading.Timer class, which is a slightly nicer wrapper.
What problems have you seen so far?
I agree with previous comment that might be best to consider a different approach. My suggest would be write a console application and use the windows scheduler:
This will:
- Reduce plumbing code that replicates scheduler behaviour
- Provide greater flexibility in terms of scheduling behaviour (e.g. only run on weekends) with all scheduling logic abstracted from application code
- Utilise the command line arguments for parameters without having to setup configuration values in config files etc
- Far easier to debug/test during development
- Allow a support user to execute by invoking the console application directly (e.g. useful during support situations)
As already stated both System.Threading.Timer
and System.Timers.Timer
will work. The big difference between the two is that System.Threading.Timer
is a wrapper arround the other one.
System.Threading.Timer
will have more exception handling whileSystem.Timers.Timer
will swallow all the exceptions.
This gave me big problems in the past so I would always use 'System.Threading.Timer' and still handle your exceptions very well.
I know this thread is a little old but it came in handy for a specific scenario I had and I thought it worth while to note that there is another reason why System.Threading.Timer
might be a good approach. When you have to periodically execute a Job that might take a long time and you want to ensure that the entire waiting period is used between jobs or if you don't want the job to run again before the previous job has finished in the case where the job takes longer than the timer period. You could use the following:
using System;
using System.ServiceProcess;
using System.Threading;
public partial class TimerExampleService : ServiceBase
{
private AutoResetEvent AutoEventInstance { get; set; }
private StatusChecker StatusCheckerInstance { get; set; }
private Timer StateTimer { get; set; }
public int TimerInterval { get; set; }
public CaseIndexingService()
{
InitializeComponent();
TimerInterval = 300000;
}
protected override void OnStart(string[] args)
{
AutoEventInstance = new AutoResetEvent(false);
StatusCheckerInstance = new StatusChecker();
// Create the delegate that invokes methods for the timer.
TimerCallback timerDelegate =
new TimerCallback(StatusCheckerInstance.CheckStatus);
// Create a timer that signals the delegate to invoke
// 1.CheckStatus immediately,
// 2.Wait until the job is finished,
// 3.then wait 5 minutes before executing again.
// 4.Repeat from point 2.
Console.WriteLine("{0} Creating timer.\n",
DateTime.Now.ToString("h:mm:ss.fff"));
//Start Immediately but don't run again.
StateTimer = new Timer(timerDelegate, AutoEventInstance, 0, Timeout.Infinite);
while (StateTimer != null)
{
//Wait until the job is done
AutoEventInstance.WaitOne();
//Wait for 5 minutes before starting the job again.
StateTimer.Change(TimerInterval, Timeout.Infinite);
}
//If the Job somehow takes longer than 5 minutes to complete then it wont matter because we will always wait another 5 minutes before running again.
}
protected override void OnStop()
{
StateTimer.Dispose();
}
}
class StatusChecker
{
public StatusChecker()
{
}
// This method is called by the timer delegate.
public void CheckStatus(Object stateInfo)
{
AutoResetEvent autoEvent = (AutoResetEvent)stateInfo;
Console.WriteLine("{0} Start Checking status.",
DateTime.Now.ToString("h:mm:ss.fff"));
//This job takes time to run. For example purposes, I put a delay in here.
int milliseconds = 5000;
Thread.Sleep(milliseconds);
//Job is now done running and the timer can now be reset to wait for the next interval
Console.WriteLine("{0} Done Checking status.",
DateTime.Now.ToString("h:mm:ss.fff"));
autoEvent.Set();
}
}
참고URL : https://stackoverflow.com/questions/246697/best-timer-for-using-in-a-windows-service
'IT story' 카테고리의 다른 글
Matplotlib : "알 수없는 투영 '3d'"오류 (0) | 2020.08.06 |
---|---|
XDocument와 함께 XPath를 사용하는 방법? (0) | 2020.08.06 |
ASP.Net 양식에 제출 된 게시물 데이터 읽기 (0) | 2020.08.06 |
react.js의 인스턴스 v 상태 변수 (0) | 2020.08.06 |
여러 페이지 앱에서 React 사용 (0) | 2020.08.06 |