2013-05-24 2 views
-2

System.Timers.Timer를 사용하여 다음 시나리오를 가지고 있습니다. System.Timers.Timer 메서드 내에서 스레드

는 Timer 객체를 생성하고 JobListener_Elapsed 내에서 방법을

_JobListener.Enabled = false; 
_JobListener.Elapsed += (this.JobListener_Elapsed); 

을 할당, 나는 몇 가지 기능을 실행하는 다른 스레드를 만들었습니다.

JobListener_Elapsed 
{ 
    //stop the timer 
    _JobListener.Enabled = false; 

    System.Threading.Thread pollThread = new Thread(JobListener_ElapsedAsync); 
    pollThread.Start(); 

    //join to the main timer thread 
    pollThread.Join(); 

    //restart the timer 
    _JobListener.Enabled = true; 
} 

나는 타이머 활성화 상태를 기록합니다.

private void JobListener_ElapsedAsync() 
{ 
    try{ 
     log Timer.Enabled 
     some other code 
    }finally 
    { 
     _JobListener.Enabled = true; 
    } 
} 

그러나 나는 몇 시간을 볼 수 있는데, 타이머 상태가 참임을 알 수 있습니다. JobListener_ElapsedAsync가 실행 중일 때 타이머를 중지해야합니다.

아이디어가 있으십니까?

+8

시작하는 스레드가 완료 될 때까지 차단을 시작하면 새 스레드를 시작할 시점이 무엇입니까? 만약 당신이 그것을하고 있다면 이벤트 처리기에서 코드를 직접 실행할 수도 있습니다. – Servy

+0

@Servy 나는 같은 질문을 나 자신에게 요구하고 있었다. 레거시 코드입니다. 별도의 스레드를 사용하지 않도록 수정했습니다. 그러나 Timer 메서드 안에이 별도의 스레드를 유지할 때이 동작에 혼란스러워합니다. – Helic

+1

코드에서 타이머를 활성화하는 위치는 어디입니까? * 어딘가에 * 활성화해야합니다. 이 코드가 실행되는 동안 아마도 호출되고있을 것입니다. 당신은 또한 여러 개의 경과 된 처리기를 가질 수 있습니다, 당신은 단지 이것을 잘못 관찰 할 수 있습니다. 비동기 메서드가 다른 * 비동기식 연산을 시작할 수 있습니다. 따라서 현재 스레드가 타이머를 사용 가능하게합니다. 문제가 무엇인지 알 수있는 충분한 코드를 보여주었습니다. – Servy

답변

3

.NET Framework에는 타이머와 창 타이머의 두 가지 주요 클래스가 있습니다.

System.Threading.Timer은 스레드 타이머의 기본 클래스입니다. 이것은 Windows waitable timer object을 래핑합니다. 에서 Tick 이벤트가 발생합니다. 인 경우 Tick을 다시 실행하기 전에 이전 Tick의 모든 처리기가 반환되었는지 확인하십시오. 타이머는 제 시간에 발사해야하며 지연되지 않습니다.

System.Windows.Forms.Timer은 Windows SetTimer API를 래핑합니다. Tick 이벤트는 타이머를 만드는 스레드에서 시작됩니다. UI 스레드가 아닌 경우에는 실제로 실행되지 않습니다. 타이머는 가장 낮은 우선 순위의 메시지입니다. 다른 메시지가없는 경우에만 GetMessage/PeekMessage에 의해 생성됩니다. 따라서 생성되어야 할 때부터 상당히 지연 될 수 있습니다.

System.Timers.TimerSystem.Threading.Timer입니다. SynchronizingObject 속성을 무언가로 설정 한 경우 기본 타이머가 작동하면 ISynchronizeInvoke.Invoke을 사용하여 해당 개체의 스레드로 이동합니다 (Control.Invoke- 실제로 ControlISynchronizeInvoke을 구현 함). 프로세스의 스레드 풀 스레드를 차단합니다. SynchronizingObjectnull이면 스레드 풀 스레드에서 Elapsed 이벤트가 발생합니다. 이 클래스의 유일한 실제 용도는 UI 구성 요소를 제 시간에 맞추기위한 타이머가 필요한 경우입니다. 동기화 할 필요가없는 경우 System.Threading.Timer을 대신 사용하십시오.

  • 정기적보다는 타이머 원샷을 확인하십시오 : 당신이 이전 Tick 이벤트가 완전히 다음 일을 시작하기 전에 (모든 핸들러가 돌아왔다) 처리되어 있는지 확인해야하는 경우

    은, 당신도 할 필요가 , 마지막 핸들러는

  • lock 또는 Monitor 핸들러를 입력하는 두 개의 스레드를 방지하기 위해 (하지만 당신은 스레드 풀에서 모든 스레드까지 사용할 수있다) 만 입력
  • 사용 Monitor.TryEnter에 사용 실행을 종료 할 또 다른 기회를 설정 한 핸들러가 이전의 경우 네가 끝났습니다 (하지만 당신은 약간 Tick을 놓칠 수 있습니다).
+0

이전 Tick 이벤트를 완전히 처리 할 수있는 솔루션에 대해 좀 더 설명 할 수 있습니까? 감사. – Helic

관련 문제