2009-05-15 5 views
1

기본적으로 사서함에 액세스하고 전자 메일을 읽는 Windows 서비스가 있습니다. 나는 매 x 초마다 사서함을 확인하는 가장 좋은 방법을 찾아 내려고 노력 중이다.x 초마다 Windows 서비스를 호출/시작하는 가장 좋은 방법은 무엇입니까?

한 가지 방법은 Thread.Sleep을 호출 한 다음 Start Method를 다시 호출하는 것입니다.

protected override void OnStart(string[] args) 
{ 
    // get config settings 
    CheckMailbox(); 
} 

public void CheckMailbox() 
{ 
    int x = 5000; 

    // do stuff 

    Thread.Sleep(x); 
    CheckMailbox(); 
} 

이것이 최선의 방법인지 확실하지 않습니다. 그런 다음이를 더 자세히 살펴 보려면 WCF를 통해 서비스를 노출하여 Windows 서비스를 호출 할 수 있음을 알고 있습니다. 이 경우 웹 응용 프로그램이 Process라는 프로세스를 호출하면 충돌하는 스레드가 생깁니다. 그러면 어떻게 처리할까요? 매번 새로운 스레드를 만들어서 큐에 넣어야합니까?

답변

7

잠자는 것은 대개 나쁜 생각입니다. 그 외의 다른 것들은 당신이 Stop 이벤트에 신속하게 응답하지 않는다는 것을 의미합니다.

Timer을 사용해야합니다.

는 각각의 경우에 당신은 기본적으로 타이머 "틱"당신이 그것을 원하는 경우에 때마다 일이하고 싶은 말 : 서비스에 대한 적절한있는 두 가지가 있습니다 불.

내 스레딩 자습서에는 section explaining some of the differences between available timers이 있습니다.

귀하의 WCF 질문에 대해 확실하지 않지만 귀하의 웹 서비스가 명시 적으로 서비스를 시작할 것이라고 생각하지 않습니다. 단지 WCF를 통해 연락 할 것입니다. 예, 잠재적으로 스레드에주의해야합니다. 정확히 당신이 조심해야 할 것은 WCF 서비스가 드러내는 것에 달려 있습니다.

+0

+1 - 좋은 지적입니다! 잠자는 동안, 서비스는 이벤트를 중지시키지 않을 것입니다. 사실입니다. –

+0

스레딩 타이머를 사용할 때마다 10 초마다 사서함을 확인하고 열거 나 처리하는 데 10 초 이상이 걸린다 고하면 여러 스레드가 한 번에 올바르게 실행됩니다. – mickyjtwin

+0

+1 타이머가 유용합니다! @mickyjtwin : System.Timers.Timer를 사용하는 경우 Start 및 Stop 메서드가 있으므로 Stop을 호출하고 메일을 처리 한 다음 Start를 호출 할 수 있습니다. 그렇게하면 다음 번에 확인할 때까지 메일 처리가 끝난 후 x 초가 기다리게됩니다. 그러나, 나는 당신이 제안한 경우에는 평행선을 얻을 것이라고 생각하지 않는다. Tick은 새 스레드가 아닌 타이머가 작성된 스레드에서 호출해야합니다. –

0

예를 들어 로그인하지 않은 상태에서 백그라운드에서 서비스로 실행하려면이 방법을 사용하는 것이 좋습니다.

5 초마다 "Tick"이벤트 처리기를 호출하는 Timer가 있어야합니다.

수표가 자주 사용되지 않는 경우 명령 줄 콘솔 앱을 만들고 Windows에서 "예약 된 작업"으로 예약 할 수도 있습니다.

마크

0

귀하의 코드는 자체 내에서 메소드를 호출하기 때문에, 모든 호출의 호출 스택에 추가하는 문제가있다. 어떤 시점에서 스택 오버플로 예외가 발생합니다. 한 대기는 일정 시간 후에 다시 신호 것 "대기 스레드"다른 메서드를 호출하는 것입니다

private void CheckMailBox() 
{ 
    _waitHandle = new AutoResetEvent(true); 
    while (_waitHandle.WaitOne()) 
    { 
     // do the mail checking 
     ((IDisposable)_waitHandle).Dispose(); 
     _waitHandle = new AutoResetEvent(false); 
     ThreadPool.QueueUserWorkItem(WaitSomeTime, 2000); 
    } 

} 

private void WaitSomeTime(object state) 
{ 

    Thread.Sleep((int)state); 
    _waitHandle.Set(); 
} 
1

기본이 System.Threading.Timer을 코드 :

// Class level variable in the Windows Service: 
private System.Threading.Timer timer; 

// This is in the constructor for a Windows Service. 
// interval would be the time in milliseconds in between ticks. 
// 0 is how long until it should start. 
timer = new Timer(new TimerCallback(TimerElapsed), null, 0, interval); 

// The TimerCallback in the Windows Service: 
private void TimerElapsed(object o) 
{ 
    // Do email stuff here. 
} 
0

사용 a 이상 가능한 강화 타이머는 서비스에서 일정 구성 요소를 사용하는 것입니다. 그런 다음 서비스를 사서함에 액세스하는 코드의 호스트로 설정할 수 있습니다.

Quartz.NET은이를 수행 할 수있는 오픈 소스 스케줄링 구성 요소입니다. 원하는대로 일정을 정확하게 설정할 수 있으므로 사용하기가 쉽습니다.

0

좋아요, 타이밍 질문이 꽤 많이 처리되는 동안 (그리고 나는 대부분 위와 동의 할 것입니다.) WCF에 관한 몇 가지 정보를 제공 할 수 있습니다. WCF 서비스는 단순히 응용 프로그램 도메인 내에서 호스팅됩니다. 이 도메인은 Windows 폼, 콘솔 응용 프로그램, ASP.net 및이 경우 Windows 서비스 일 수 있습니다.

그래서 어떤 의미에서, 당신은 를 통해 WCFWindows 서비스를 노출하지 않는, 당신은 Windows 서비스 응용 프로그램 도메인 내에서 WCF 서비스 호스팅 더있어. Windows 서비스로 전환하기 전에 windows 양식에 서비스 (타이머 개체 포함)를 테스트하는 것이 좋습니다. 디버깅 및 테스트가 더 쉽습니다. 는 "DerivativesCalculatorService"예를 들어

serviceType_MyEmailer = typeof(MyEmailerServiceType); 
    ServiceHost host_MyEmailer; 


    host_MyEmailer = new ServiceHost(serviceType_MyEmailer); 

봐 온라인 :

는 A는 WCF 서비스가 실제로 자신의 스레드에서 실행되고있는 호스트. 코드에서 WCF 서비스를 호스팅하는 방법을 보여줍니다.

타이밍 트릭은 서비스 자체 내에 있습니다. 서비스 클래스를 생성하여 즉시 초기화되는 싱글 톤 클래스로 만들 수 있으며 초기화시 (다른 답변 에서처럼) Timer 객체를 시작할 수 있습니다.

이렇게하면 WCF 서비스에는 Timer 개체가 조용히 켜져있는 클래스의 영구 인스턴스가 있습니다. 모든 것을 Windows 서비스에 호스팅하면 완료됩니다.

희망이 도움이됩니다.

관련 문제