C # 프로그램을 50msec 동안 절전 모드로 전환하려면 어떻게합니까?


272

C # 프로그램을 50 밀리 초 동안 절전 모드로 전환하려면 어떻게합니까?

이것은 쉬운 질문처럼 보이지만 일시적인 뇌 장애 순간을 겪고 있습니다!


1
대답이 작동하기 때문에 VB.NET에 다시 태그를 지정했습니다.
DrFloyd5

DrFloyd5 없음; VB.NET에서 작동하지 않습니다.
Zanoni

16
내가 VB.Net 팀에 있었다면 추가하겠습니다; 언어의 다음 버전에 대한 설명 문자로 ...
Joel Coehoorn

4
VB 프로그래머는 그와 동등한 것을 알아낼 수있을만큼 밝다고 생각합니다.
BlueRaja-Danny Pflughoeft

글쎄, 단지 확인하기 위해, 이제 그들은 할 필요가 없습니다.
PsychoData

답변:


330
System.Threading.Thread.Sleep(50);

그러나 기본 GUI 스레드에서이 작업을 수행하면 GUI 업데이트가 차단됩니다 ( "느린 느낌").

그냥 제거 ;VB.net에서도 작동하도록하려면를 .


메소드에서 sleep을 호출 한 후 프로그램이 백그라운드에서 계속 실행됩니까 (새 스레드를 작성하지 않고)? 또한 새 스레드에서 절전 모드를 호출하면 기본 스레드가 계속 작동합니까?
Jay Nirgudkar

@JayNirgudkar Sleep을 호출하는 스레드가 중지됩니다. 다른 스레드는 영향을받지 않습니다.
Isak Savo

정확하지는 않습니다.
Akumaburn

150

기본적으로 프로그래밍 언어를 기다리는 방법은 3 가지가 있습니다.

  1. 느슨한 대기
    • 주어진 시간 동안 스레드 블록 실행 (= 처리 능력을 소비하지 않음)
    • 차단 / 대기 스레드에서 처리 할 수 ​​없습니다
    • 너무 정확하지
  2. 타이트 대기 (타이트 루프라고도 함)
    • 전체 대기 간격 동안 프로세서가 매우 사용 중입니다 (사실, 일반적으로 하나의 코어 처리 시간의 100 %를 소비 함)
    • 기다리는 동안 일부 작업을 수행 할 수 있습니다
    • 매우 정확한
  3. 이전 2의 조합
    • 일반적으로 1의 처리 효율성과 정확성 + 2의 작업 수행 능력을 결합합니다.

-C #에서 느슨하게 대기 :

Thread.Sleep(numberOfMilliseconds);

그러나 Windows 스레드 스케줄러는 정확성을 유발합니다. Sleep() 가 약 15ms가되도록합니다 (따라서 1ms 동안 대기하도록 예약되어 있어도 절전 모드가 20ms 동안 쉽게 대기 할 수 있음).

-C #에서 꽉 기다리는 것은 다음과 같습니다.

Stopwatch stopwatch = Stopwatch.StartNew();
while (true)
{
    //some other processing to do possible
    if (stopwatch.ElapsedMilliseconds >= millisecondsToWait)
    {
        break;
    }
}

우리는 또한 DateTime.Now다른 시간 측정 수단을 사용할 수도 있지만 Stopwatch훨씬 빠릅니다 (이것은 빡빡한 루프에서 실제로 볼 수 있습니다).

3 인용-조합 :

Stopwatch stopwatch = Stopwatch.StartNew();
while (true)
{
    //some other processing to do STILL POSSIBLE
    if (stopwatch.ElapsedMilliseconds >= millisecondsToWait)
    {
        break;
    }
    Thread.Sleep(1); //so processor can rest for a while
}

이 코드는 스레드를 1ms (또는 OS 스레드 스케줄링에 따라 약간 더) 동안 정기적으로 차단하므로 프로세서는 차단 시간 동안 사용 중이 아니며 코드는 프로세서 전력의 100 %를 소비하지 않습니다. UI 처리, 이벤트 처리 또는 상호 작용 / 통신 작업과 같은 다른 처리는 여전히 차단간에 수행 될 수 있습니다.


1
타이머 또한 관심을 가질만한 것입니다
JonnyRaa

55

Windows 에서는 정확한 절전 시간을 지정할 수 없습니다 . 이를 위해서는 실시간 OS가 필요합니다. 최선의 방법은 최소 절전 시간을 지정하는 것입니다. 그런 다음 스레드를 깨우는 것은 스케줄러에 달려 있습니다. 그리고 GUI 스레드를 절대 호출 하지 마십시오.Sleep() .


44

이제 비동기 / 대기 기능이 있으므로 50ms 동안 절전 모드로 전환하는 가장 좋은 방법은 Task.Delay를 사용하는 것입니다.

async void foo()
{
    // something
    await Task.Delay(50);
}

또는 .NET 4 (VS2010 또는 Microsoft.Bcl.Async 용 Async CTP 3 사용)를 대상으로하는 경우 다음을 사용해야합니다.

async void foo()
{
    // something
    await TaskEx.Delay(50);
}

이렇게하면 UI 스레드를 차단하지 않습니다.


루프 상태 인 경우이 지연 시간 동안 response.flush를 수행 할 수 있습니까?
Teoman shipahi

아니 당신은 할 수 없습니다. FlushAsync버전 이 있다고 생각 합니다.
Toni Petrina

6
async선언이 필요없는 대안 은 전화하는 것입니다Task.Delay(50).Wait();
stuartd


14
Thread.Sleep(50);

스레드는 지정된 시간 동안 운영 체제에서 실행되도록 예약되지 않습니다. 이 메소드는 스레드 상태를 WaitSleepJoin을 포함하도록 변경합니다.

이 방법은 표준 COM 및 SendMessage 펌핑을 수행하지 않습니다. STAThreadAttribute가있는 스레드에서 휴면 상태를 유지해야하지만 표준 COM 및 SendMessage 펌핑을 수행하려는 경우 시간 초과 간격을 지정하는 Join 메서드의 오버로드 중 하나를 사용하는 것이 좋습니다.

Thread.Join

5

가독성을 위해 :

using System.Threading;
Thread.Sleep(TimeSpan.FromMilliseconds(50));

0

.NET Framework 4.5부터 다음을 사용할 수 있습니다.

using System.Threading.Tasks;

Task.Delay(50).Wait();   // wait 50ms

-1

두 세계의 최고:

using System.Runtime.InteropServices;

    [DllImport("winmm.dll", EntryPoint = "timeBeginPeriod", SetLastError = true)]
    private static extern uint TimeBeginPeriod(uint uMilliseconds);

    [DllImport("winmm.dll", EntryPoint = "timeEndPeriod", SetLastError = true)]
    private static extern uint TimeEndPeriod(uint uMilliseconds);
    /**
     * Extremely accurate sleep is needed here to maintain performance so system resolution time is increased
     */
    private void accurateSleep(int milliseconds)
    {
        //Increase timer resolution from 20 miliseconds to 1 milisecond
        TimeBeginPeriod(1);
        Stopwatch stopwatch = new Stopwatch();//Makes use of QueryPerformanceCounter WIN32 API
        stopwatch.Start();

        while (stopwatch.ElapsedMilliseconds < milliseconds)
        {
            //So we don't burn cpu cycles
            if ((milliseconds - stopwatch.ElapsedMilliseconds) > 20)
            {
                Thread.Sleep(5);
            }
            else
            {
                Thread.Sleep(1);
            }
        }

        stopwatch.Stop();
        //Set it back to normal.
        TimeEndPeriod(1);
    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.