2012-04-09 3 views
2

나는 3 개의 분리 된 타이머 사이에서 끊임없이 저글을 시작하는 프로그램을 가지고있다.C# 프로그램이 너무 많은 CPU를 사용하고 있습니까?

내 응용 프로그램의 주 스레드는 전역 변수가 true로 설정되어 있는지 계속 확인하는 while 루프가 있으며,있을 경우 하나의 타이머를 중지하고 두 개의 다른 타이머를 시작합니다. 하나는 지속적으로, 다른 하나는 자동으로 중지합니다 어떤 이유로 든 멈추라는 명령을받지 않은 경우.

이 while 루프는 조건이 (1 == 1)이므로 영원히 계속 실행됩니다.

작업 관리자 (XP)에서 프로그램이 다소 유휴 상태 인 시스템에서 CPU의 50 %를 사용하고있는 것으로 나타났습니다.

while 루프 또는 그 밖의 속도를 줄여서이 수를 줄이는 방법이 있습니까?

감사합니다.

+0

무한 루프로 3 개의 스레드를 실행하고 계신 것 같습니까? 끝내지 않는 루프는 피해야하기 때문에 [Thread.Interrupts] (http://msdn.microsoft.com/en-us/library/system.threading.thread.interrupt.aspx)를 확인하십시오! –

+0

루프가 절전 모드입니까? 논스톱을 돌면서 거기에 앉아 있으면 CPU 사용량을 설명 할 수 있습니다 (아마도 단일 코어의 100 %를 사용합니까?). 아마도 각 반복 끝에 수 밀리 초 동안 절전 모드로 들어갔다면 CPU 사용량은 더 적을 것입니다. –

+0

@dsp 코드를 게시 할 수 있습니까? –

답변

4

while 루프의 속도를 줄이면 그 수를 줄일 수 있습니까?

예, Thread.Sleep(n)에 전화를 걸 수 있습니다. ~ 20 밀리 세컨드의 입도.

하지만 더 나은 옵션은 Waithandle을 사용하는 것입니다.
주 스레드는 핸들을 기다리면 타이머 코드의 끝에서 깨어 신호를 보냅니다.

+0

빠르고 더러운 수정을 보내 주셔서 감사합니다.) –

+0

100 % CPU 잡는 것을 피하기 위해 "0"으로 전달하는 것으로 충분합니다. (실제로 생성 된 실제 시간은 Windows 스케줄 세분성 "20ms"로 인해 "0"보다 약간 더 많습니다.) –

+1

@pst : 일부 상황에서는 절전 모드 (0)에 문제가 있습니다. 일반적으로 수면 (1)을 사용하십시오. –

11

while 루프의 속도를 줄이면 그 수를 줄이는 방법이 있습니까?

바쁜 루프를 중지하십시오. 스레드간에 이벤트를 조정하는 더 나은 방법이 있습니다. Monitor.Wait/Pulse 또는 AutoResetEvent/ManualResetEvent을 사용하는 것이 좋습니다. 기본적으로 전역 변수를 설정하는 스레드는 그렇게했음을 알려야합니다. 또는 기본 스레드가 그 밖의 것을 수행하지 않을 경우 일반 C# 이벤트를 추가하여 변수가 변경 될 때마다 이벤트가 발생하고 적절한 조치가 취해 지도록하십시오.

2

주어진 시간 (ms) 동안 위협을 중지해야합니다. Thread.sleep() 함수를 살펴보고 while 루프 내에 배치하십시오.

2

루프를 느리게하는 가장 쉬운 방법은 System.Threading.Thread.Sleep (100)을 추가하는 것입니다. 모든 반복에 대해 프로세스는 100ms 동안 잠자기 상태가되며 더 이상 50 % CPU를 사용하지 않습니다.

+0

Jon의 답변 "바쁜 일을 그만 두십시오"는 최고의 충고입니다. 그러나 수면을 추가하는 것은 빠르고 지저분한 수정입니다. – rgullhaug

6

프로그램이 busy waiting을 수행합니다. 이는 나쁜 습관입니다. 루핑 대신 일종의 동기화 프리미티브 (wait handle라고도 함)를 차단하도록 논리를 변경해야합니다. 대기 핸들을 차단

는 UI 스레드에 대한 옵션이 없습니다, 그래서 당신은 총 세 개의 스레드를 생성해야하고이 같은 계획 구현합니다 :

  1. UI 스레드가 모두 자신을 염려하지 않습니다 다른 스레드로. 반복 없음, 수면 없음, 차단 없음.
  2. 새 "컨트롤러"스레드는 기존 "작업자"스레드를 시작한 다음 (예 : 신호가 보내지지 않은 이벤트에서) 즉시 차단합니다.이 이벤트는 이벤트가 발생할 때까지 (즉 "작업자"가 완료 될 때까지) CPU를 소비하지 않고이 상태로 유지됩니다.
  3. "작업자"스레드는 해당 과정을 실행 한 다음 이벤트를 신호로 보냅니다.
2

스레드 대신 타이머 대신 스레드를 사용할 수 있습니다. 또는 다른 스레드가 시작되기 전에 중단 된 스레드의 스레드 상태를 확인하십시오. 코드 논리를 줄임으로써 성능을 향상시킬 수 있습니다.

희망이 도움이 될 것입니다. :)

0

여기에 대한 답변은 틀린 것은 아니지만 while(true) 루프를 수행 할 때 많은 문제를 실제로 처리하지는 않습니다. 이는 while(1==1)입니다.

첫 번째로, 루프가 응용 프로그램이 사용되는 전체 시간 동안 실행 되더라도, 사용자가 응용 프로그램을 종료 할 때 어떤 지점에서 똥을 내고 싶을 것입니다. 왜냐하면 상수가있는 스레드가 있기 때문입니다 루프를 실행해도 사용자가 UI 창을 닫더라도 프로세스는 스레드가 종료 될 때까지 유지됩니다 (절대로 참 루프가 아닙니다). 또는 사용자가 현명 해져서 작업 관리자에서 닫힐 때까지 프로세스가 유지됩니다.

루프 밖에서 접근 가능한 속성을 참조하는 while 조건부 검사에 참 조건부를 넣으면이 문제를 해결할 수 있습니다.

예 :

베어 뼈이며, 심지어 이중 출시 또는 더블 종료 이벤트를 피하는으로하지 않습니다
private bool RequestExit = false; 
private Thread MyLoopThread; 
private void MyLoop() 
{ 
    while (!RequestExit) 
    { 
    //Do stuff! 
    Sleep(1); 
    } 
} 
public void StartLoop() 
{ 
    RequestExit = false; 
    MyLoopThread = new Thread(MyLoop); 
    MyLoopThread.Start(); 
} 
public void StopLoop() 
{ 
    RequestExit = true; 
} 

.

훨씬 깨끗한 방법은 풀로 만들려는 임의의 간격을 설정하는 것입니다. 10ms 정도면 실시간 이벤트가 거의 발생하지 않아야하며 해당 간격으로 실행하는 메소드를 트리거해야합니다.

private Timer DoStuffTimer; 
private void DoStuffMethod(object obj = null) 
{ 
    //Do stuff! 
} 
public void StartLoop() 
{ 
    DoStuffTimer = new Timer(DoStuffMethod,null,10,10); 
} 
public void StopLoop() 
{ 
    DoStuffTimer.Dispose(); 
} 
관련 문제