[C#] 실시간 이전 스레드가 여전히 바쁠 경우 Timer가 틱을 건너 뛰게하는 방법

홈 > Program > Windows
Windows

[C#] 실시간 이전 스레드가 여전히 바쁠 경우 Timer가 틱을 건너 뛰게하는 방법

최고관리자 0 71

c# timer 정밀도 (7)

Windows 서비스를 만들었는데, db의 특정 테이블을 매 60 초마다 확인해야합니다. 추가 된 모든 새로운 행에 대해 서버에서 60 초 이상 걸릴 수있는 무거운 프로세싱을 수행해야합니다.

내 서비스에서 Timer 객체를 만들었습니다.이 객체는 매 60 초마다 틱하고 원하는 메서드를 호출합니다. 
발견 된 새 행을 처리하는 동안이 타이머를 틱하지 않으려면  lock { }  블록에 메서드를 래핑 했으므로 다른 스레드가 액세스 할 수 없습니다.

다음과 같이 보입니다.

         Timer serviceTimer =newTimer();
serviceTimer.Interval=60;
serviceTimer.Elapsed+=newElapsedEventHandler(serviceTimer_Elapsed);
serviceTimer.Start();voidserviceTimer_Elapsed(object sender,ElapsedEventArgs e){lock(this){// do some heavy processing...}}
         

자, 나는 궁금해하고있다. 
내 타이머가 똑딱 거리고 db에 새로운 행이 많이 있고 처리가 60 초 이상 걸리면 이전 틱이 끝날 때까지 다음 틱은 처리를하지 않습니다. 이것이 내가 원하는 효과이다.

그러나 이제는 첫 번째 처리가 완료되면 serviceTimer_Elapsed 메소드가 즉시 꺼 지거나 타이머가 다시 똑딱 거리기를 기다릴 것입니다.

내가 원하는 것은 처리가 60 초 이상 필요하다면 타이머가 스레드가 잠겨 있다는 것을 알아 차리고 다시 60 초 동안 기다려서 스레드의 큐가있는 상황에서 결코 멈추지 않을 것입니다. 이전의 것을 끝내기를 기다린다.

어떻게이 결과를 얻을 수 있습니까? 
이 작업을 수행하는 가장 좋은 방법은 무엇입니까?

감사!


Answer #1

타이머를 멈추는 대신 타이머가 계속 똑딱 거리고 잠금을 얻을 수있을 때만 작업을 수행 할 수있는 다른 대답과 유사한 변형입니다.

경과 이벤트 핸들러에 넣으십시오.

                  if(Monitor.TryEnter(locker){try{// Do your work here.}finally{Monitor.Exit(locker);}}
                  

Answer #2

이 경우에는 자물쇠가 필요 없습니다. 타이머를 시작하기 전에 timer.AutoReset = false로 설정하십시오. 처리가 끝나면 처리기에서 타이머를 다시 시작하십시오. 이렇게하면 각 작업  타이머가 60 초 동안 실행됩니다.


Answer #3

또 다른 확실성은 다음과 같습니다.

                  voidserviceTimer_Elapsed(object sender,ElapsedEventArgs e){if(System.Threading.Monitor.IsLocked(yourLockingObject))return;elselock(yourLockingObject)// your logic  ;}
                  

Answer #4

처리하는 동안 타이머가 전혀 작동하지 않도록하는 것이 좋습니다.

타이머 AutoReset을 false로 설정하십시오. 끝에서 시작하십시오. 관심이있을만한 전체 대답은 다음과 같습니다 . DB의 작업 대기열에서 작업을 실행하는 Windows 서비스. 구함 : 예제 코드


Answer #5

서비스가 실행 중인지 빠르게 확인하십시오. 실행중인 경우이 이벤트를 건너 뛰고 다음 이벤트가 발생할 때까지 기다립니다.

                  Timer serviceTimer =newTimer();
serviceTimer.Interval=60;
serviceTimer.Elapsed+=newElapsedEventHandler(serviceTimer_Elapsed);
serviceTimer.Start();bool isRunning =false;voidserviceTimer_Elapsed(object sender,ElapsedEventArgs e){lock(this){if(isRunning)return;
        isRunning =true;}try{// do some heavy processing...}finally{
        isRunning =false;}}
                  

Answer #6

다른 옵션으로는 BackGroundWorker 클래스 또는 TheadPool.QueueUserWorkItem을 사용할 수 있습니다.

배경 작업자는 여전히 발생하고있는 현재 처리 옵션을 한 번에 하나씩 처리 할 수있는 옵션을 쉽게 제공합니다. ThreadPool은 필요한 경우 틱 (tick)마다 항목을 대기열에 계속 대기시킬 수있는 기능을 제공합니다.

설명에서 데이터베이스의 대기열에있는 항목을 확인한다고 가정합니다. 이 경우 ThreadPool을 사용하여 작업을 백그라운드로 푸시하고 느린 속도로 / 검사 메커니즘을 중지하지 마십시오.

서비스의 경우 ThreadPool 방식을 사용하는 것이 좋습니다 . 이렇게하면 타이머로 60 초마다 새 항목을 확인한 다음 대기열에 넣고 .Net에서 각 항목에 할당 할 금액을 파악하고 항목을 대기열에 계속 푸시 할 수 있습니다.

예 : 타이머 만 사용하고 5 개의 새로운 행이있는 경우 65 초의 처리 시간이 필요합니다. ThreadPool 방식을 사용하면 5 초의 배경 작업 항목으로 65 초 만에 완료됩니다. Timer 방식을 사용하면 4 분 이상 (각 행 사이에 대기하는 시간)이 소요되며 대기열에있는 다른 작업의 백 로그가 발생할 수 있습니다.

이 작업을 수행하는 방법의 예는 다음과 같습니다.

                  Timer serviceTimer =newTimer();voidstartTimer(){
        serviceTimer.Interval=60;
        serviceTimer.Elapsed+=newElapsedEventHandler(serviceTimer_Elapsed);
        serviceTimer.AutoReset=false;
        serviceTimer.Start();}voidserviceTimer_Elapsed(object sender,ElapsedEventArgs e){try{// Get your rows of queued work requests// Now Push Each Row to Background Thread Processingforeach(Row aRow inRowsOfRequests){ThreadPool.QueueUserWorkItem(newWaitCallback(longWorkingCode), 
                    aRow);}}finally{// Wait Another 60 Seconds and check again
            serviceTimer.Stop();}}voidlongWorkingCode(object workObject){Row workRow = workObject asRow;if(workRow ==null)return;// Do your Long work here on workRow}
                  

Answer #7

처리 중에 타이머를 사용하지 않도록 설정할 수 있습니다.

                  // Just in case someone wants to inherit your class and lock it as well ...privatestaticobject _padlock =newobject();try{
  serviceTimer.Stop();lock(_padlock){// do some heavy processing... }}finally{
  serviceTimer.Start();}
                  

편집 : OP는 재진입 성이 타이머에 의해서만 발생했는지 또는 서비스가 다중 스레드 였는지 여부를 지정하지 않았습니다. 나중에 가정했는데 타이머가 멈 추면 (자동 재설정 또는 수동으로) 이전 잠금이 불필요한 경우,

Author

Lv.99 최고관리자  최고관리자
5,086,838 (100%)

등록된 서명이 없습니다.

0 Comments
제목
Category
State
  • 현재 접속자 45 명
  • 오늘 방문자 1,168 명
  • 어제 방문자 1,168 명
  • 최대 방문자 3,964 명
  • 전체 방문자 714,170 명
  • 전체 게시물 2,795 개
  • 전체 댓글수 1 개
  • 전체 회원수 45 명
Facebook Twitter GooglePlus KakaoStory KakaoTalk NaverBand