2012-08-28 3 views
0

스레드가 X 초 이상 실행될 때 뭔가를 할 수있는 논리가 필요합니다. 이 믿을 수 없을 정도로 추악한 예에서, 여기가 매초을 확인하고 workerThread 10 분 이상 실행중인 경우이 메시지가 표시처럼스레드가 실행 된 시간을 확인하십시오.

...

var timeWorking = TimeSpan.FromMinutes(0); 
workerThread = new Thread(RunTask); 
workerThread.Start(task); 
while (workerThread.IsAlive) 
{ 
    Thread.Sleep(TimeSpan.FromSeconds(1)); 
    timeWorking = timeWorking.Add(TimeSpan.FromSeconds(1)); 
    if (timeWorking.TotalMinutes < 10) continue; 
    timeWorking = TimeSpan.FromMinutes(0); 
    Console.Writeline("Here we go... the event") 
} 

나 바로를 만들기 위해 도와주세요. .. 무엇을 사용해야합니까? Diagnostics.StopWatch, System.Timers.Timer 또는 Threading.Timer?

UPD : 모든 해답이 날 더 혼란 ...

작업은 workerThread 시간의 X 금액 이상 실행되고 있는지 확인하는 것입니다,하고 있는지, 어떤 메소드를 호출 타이머를 재설정 마지막으로 우리가 메서드를 호출 한 이후로 X 시간이 넘는 시간 동안 workerThread이 실행되고 있는지 다시 확인하십시오 ... 등등 ...

UPD2 : 기본적으로 나는 기반 처리를 수행하는 스레드가 있습니다. AmazonSQS 대기열에서 가져온 정보. SQS 대기열 메시지에 가시성 제한 시간이 있습니다. 작업이 기본 표시 시간 초과보다 오래 걸리는 경우 작업이 완료되기 전에 메시지가 대기열로 돌아갑니다. 그런 다음 다른 컴퓨터에서 가져옵니다. 이를 방지하려면 SQS 메시지의 가시성 타임 아웃을 연장해야합니다. 그럼 스레드주기가 isALive인지 주기적으로 확인하여 메시지 표시 시간 초과에 몇 분을 추가 할 수 있습니다. 1 분 50 초 정도 지나면 다시 검사해야하고 스레드가 여전히 isALive이면 몇 분 정도 더 추가해야합니다.

+0

현재 샘플에서와 같이 시간 스레드에서 CPU (실행 예정) 또는 경과 시간을 사용 하시겠습니까? –

+0

사이드 노트 : 정확한 지연을 제공하기 위해 잠을 기다리는 것은 잘못된 가정입니다. 잠자기는 요청한 시간 전에 스레드가 깨어나지 않을 것이므로 시간이 오래 걸릴 수 있습니다 - 따라서 "timeWorking"에 초를 추가하면 항상 실제 경과 시간이 짧아집니다 시각. –

답변

2

나는 당신이 묘사 한 것을 바탕으로 System.Timers.Timer이 더 적합하다고 생각합니다. 그러나, 그것은 달려있다. 타이머를 사용하여 UI로 무언가를하고 싶다면. Forms.Timer가 더 좋습니다.

어느 경우이든 타이머가 Elapsed (또는 Ticked) 일 때 스레드가 아직 살아 있는지 확인하고있을 경우 간단히 확인할 수 있습니다.

timeThreadStarted = DateTime.Now; 
    workerThread = new Thread(RunTask); 
    System.Timers.Timer timer = new System.Timers.Timer(TimeSpan.FromSeconds(1).TotalMilliseconds); 
    timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed); 
    workerThread.Start(task); 
//... 

static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
{ 
    if(workerThread != null && workerThread.IsAlive) 
    { 
     Console.WriteLine("thread has been running for {0}!", DateTime.Now - timeThreadStarted); 
    } 
} 

이 메시지는 1 초 후에 스레드 상태를 확인합니다. 여전히 Alive이면 적어도 1 초 동안 실행됩니다.

이렇게하면 스레드를 차단하지 않아도됩니다. UI가 있고이를 원할 경우 UI 스레드를 차단할 수 없습니다 (UI 스레드가 응답하지 않아 사용자 환경이 좋지 않음).

+0

@downvoter downvote에 대한 타당한 이유는 무엇입니까? –

0

경과 시간이 트리거되면 이벤트를 발생시키는 타이머를 사용할 수 있습니다.

private static void Main(string[] args) 
    { 
     var thread = new Thread(
      () => 
       { 
        var timer = new System.Timers.Timer 
         { 
          Interval = 10000, //10s 
          AutoReset = false, //only raise the elapsed event once 
         }; 
        timer.Elapsed += timer_Elapsed; 
        timer.Start(); 
        while (true) 
        { 
         Console.WriteLine("Running..."); 
         Thread.Sleep(1000); //Always put a thread to sleep when its blocking so it does not waste CPU cycles. 
        } 
       }); 
     thread.Start(); 
    } 

    private static void timer_Elapsed(object sender, ElapsedEventArgs e) 
    { 
     //thread is running for more that X (10s) amount of seconds 
     Console.WriteLine("Timer elapsed"); 
    } 

이것은 간단한 예입니다. 이 예제에서는 스레드가 종료되지 않습니다. 그러나 당신이 성취하고자하는 것을 얻기 위해 필요한 곳에 당신 자신의 논리를 추가 할 수 있습니다.

짧은 대답 : 예, System.Timers를 사용하십시오.타이머

+0

+0 : 저는 자식 스레드에서 Timer를 사용함에 따라 OP가 원했던 것보다 뒤떨어 졌다고 생각합니다 (일반적으로 타이머를 사용하는 것이 좋습니다). –

2

당신이 스레드 10 분 뭔가를 할 필요가 있음을 알고 있기 때문에, 왜 단순히이 같은 타이머 간격을 사용하지 :

var interval = 1000 * 60 * 10; // ten minutes 
var timer = new System.Timers.Timer(interval) { AutoReset = false }; 
timer.Elapsed += ((sender, eventArgs) => 
    { 
     // Do your work here... 
    }); 

workerThread = new Thread(RunTask); 
workerThread.Start(task); 
timer.Start(); 

이 방법은 각 초를 확인하지 않는 당신이 실행됩니다 원하는 시간 후에 코드를 작성하십시오. 작업이 종료되거나 타임 아웃이 발생할 때까지

+0

하지만 workerThread의 실행 시간을 어떻게 알 수 있습니까? – Agzam

+0

폴링 또는 스레드가 작업을 완료했거나 '타이머'를 통해 종료 한 후에 총 시간을 얻으면 문제가 발생합니까? 이것이 나라면 작업자 스레드가 작업을 끝내거나 Timer.Elapsed 이벤트가 발생할 때를 계산할 것입니다. 이 값으로 UI를 업데이트하는 경우 매 초마다 증가시켜 가짜 이벤트를 만든 다음 업데이트 만합니다. 이렇게하면 작업자 스레드가 느려지지 않습니다. –

-1

당신은 예를 들어,

var t = Task.Factory.StartNew(() => MyAction()); // MyAction is an action to be executed in parallel 


bool check = t.Wait(10000); //wait for 10000 milliseconds 
if (check) 
{ 
// all ok 
} 
else 
{ 
    // over time 
} 

wait 메소드 블록을 작업 대기 방법을 사용할 수 있습니다. 기본 스레드를 차단하지 않으려면 병렬로 작동하는 다른 작업을 사용하여 예제 코드를 실행하고 작업 작업을 확인할 수 있습니다.

+1

그러면 현재 스레드를 차단하게됩니다. 여기서 'Timer'는 스레드를 차단하지 못하게합니다 ... Main/UI 스레드에서 수행하면 좋지 않습니다. –

+0

내 편집 된 응답을 참조하십시오, 코드는 다른 작업에서 실행할 수 있습니다. –

+0

질문을보십시오. 작업은 타이머와 같은 다른 작업을 검사하는 데 사용할 수 있지만 작업은 한 번 실행됩니다. 타이머는 여러 번 검사를 수행하려는 경우보다 유용하지만 이는 문제가 아닙니다. –

1

예를 들어 http://msdn.microsoft.com/en-us/library/23f7b1ct.aspxTimeSpan과 같이 Thread.Join을 입력하여 Thread.Sleep을 수행 할 필요가 없도록 할 수도 있습니다.

참고 : 어느 쪽이든은 시간이 경과 할 때까지 스레드를 호출하는 블록에 접근합니다. 기본/UI 스레드에는 적합하지 않습니다.

+2

이렇게하면 하나의 스레드가 다른 스레드를 기다리는 것을 차단합니다. 특히이 검사가 기본/UI 스레드에서 수행되는 경우에는 필요하지 않습니다. –

+0

+1 원본 차단 코드를 구현하는 데 더 좋은 방법이 있습니다. 둘 다 UI 스레드에 적합하지 않습니다. –

관련 문제