2011-03-29 2 views
3

Windows 서비스의 System.Timers.Timer에 문제가 있습니다. 나는 기본적으로 다음 코드를 기본 폴링 서비스 클래스에 타이머를 설정 :System.Timers.Timer 다시 시작을 다시 설정하는 중

_serviceTimer.Elapsed += OnElapsedTime; 
_serviceTimer.Interval = ServiceTimerInterval.TotalMilliseconds; 
_serviceTimer.AutoReset = false; 
_serviceTimer.Enabled = true; 

OnElapsedTime 화재, 나는 타이머를 해제하고 조회에 따라 다른 값으로 간격을 설정하려는 경우. 문제는 타이머를 실제로 다시 시작하는 간격을 변경할 때입니다. 이 이상한 동작은 msndn 문서에서 다음과 같이 사용됩니다.

참고 :Enabled 및 AutoReset이 모두 false로 설정되어 있고 이전에 타이머를 사용하도록 설정 한 경우 Interval 속성을 설정하면 Elapsed 이벤트가 Enabled 속성이 true로 설정된 경우 이벤트를 발생시키지 않고 간격을 설정하려면 AutoReset 속성을 일시적으로 true로 설정할 수 있습니다. onelapsed 이벤트에서 Timer.Interval

나는이 있습니다

_serviceTimer.Enabled = false; 
double newIntervalSetting = newSetting; 
base._serviceTimer.AutoReset = true; 
base._serviceTimer.Interval = newIntervalSetting; 
base._serviceTimer.AutoReset = false; 
//reenable after processing 

문제는 간격 변화는 여전히 타이머 카운트 다운을 시작하고 결국 나는 변화하는 사실 이전에 자동 리셋을 설정 한 경우에도 이벤트를 발생시킵니다이다 간격. 활성화 된 상태는 항상 false이지만 이벤트는 계속 발생합니다. 나는이 작업을 수행하는 올바른 방법에 대해 msdn 문서를 오해하고 있는지 잘 모르겠습니다. 누구든지 나를 도울 수 있습니까?

+0

그래도 비참한 수업입니다. 그래서 System.Threading.Timer가 존재하는 이유입니다. –

+0

그래, 확실히 제한이있는 것 같습니다. 아래의 단축키를 사용하고 기회가 생기면 전환 할 것입니다. – gleasonomicon

답변

1

기존 OnElapsedTime 이벤트에서 부울 m_SetEnabled = true을 설정 한 다음 if(m_SetEnabled) { m_SetEnabled = false; return; }을 추가하면 실행되는 단일 이벤트 만 무시할 수 있습니다.

1

이 코드는 현재 Enabled에서 false으로 설정하는 코드와 다른 스레드에서 호출되는 EventHandler와 관련 있다고 생각합니다.

MSDN Doc에 따르면

:

항상 스레드 풀 스레드에서 실행을 위해 대기 할 때의 경과 이벤트를 발생하는 신호 때문에 이벤트 처리 방법은 동시에 하나 개의 스레드에서 실행될 수 있습니다 Stop 메서드를 에 호출하면 다른 스레드에서 실행됩니다. 이로 인해 Stop 메서드가 호출 된 후 Elapsed 이벤트가 발생할 수 있습니다. 코드 다음 절의 예제에서는 조건을 해결하기 위해 방법을 보여줍니다.

private static void HandleElapsed(object sender, ElapsedEventArgs e) 
{ 
    numEvents += 1; 

    // This example assumes that overlapping events can be 
    // discarded. That is, if an Elapsed event is raised before 
    // the previous event is finished processing, the second 
    // event is ignored. 
    // 
    // CompareExchange is used to take control of syncPoint, 
    // and to determine whether the attempt was successful. 
    // CompareExchange attempts to put 1 into syncPoint, but 
    // only if the current value of syncPoint is zero 
    // (specified by the third parameter). If another thread 
    // has set syncPoint to 1, or if the control thread has 
    // set syncPoint to -1, the current event is skipped. 
    // (Normally it would not be necessary to use a local 
    // variable for the return value. A local variable is 
    // used here to determine the reason the event was 
    // skipped.) 
    // 
    int sync = Interlocked.CompareExchange(ref syncPoint, 1, 0); 
    if (sync == 0) 
    { 
     // No other event was executing. 
     // The event handler simulates an amount of work 
     // lasting between 50 and 200 milliseconds, so that 
     // some events will overlap. 
     int delay = timerIntervalBase 
      - timerIntervalDelta/2 + rand.Next(timerIntervalDelta); 
     Thread.Sleep(delay); 
     numExecuted += 1; 

     // Release control of syncPoint. 
     syncPoint = 0; 
    } 
    else 
    { 
     if (sync == 1) { numSkipped += 1; } else { numLate += 1; } 
    } 
} 
관련 문제