web-dev-qa-db-ja.com

C#プログラムを50ミリ秒間スリープさせるにはどうすればよいですか。

C#プログラムを50ミリ秒間スリープさせるにはどうすればよいですか。

これは簡単な質問に思えるかもしれませんが、一時的な脳障害の瞬間があります。

259
TK.
System.Threading.Thread.Sleep(50);

ただし、メインのGUIスレッドでこれを実行すると、GUIの更新が妨げられることになります(「鈍い」ように感じます)。

;を削除してVB.netでも機能するようにするだけです。

309
Isak Savo

(ほぼ)あらゆるプログラミング言語で待つための基本的に3つの選択肢があります。

  1. ゆったり待っている
    • 一定時間スレッドブロックを実行する(=処理能力を消費しない)
    • ブロックされている/待機中のスレッドでは処理できません
    • そんなに正確ではない
  2. タイトな待機(タイトループとも呼ばれます)
    • プロセッサは待機時間全体にわたって非常にビジーです(実際、通常は1コアの処理時間の100%を消費します)。
    • 待機中にいくつかのアクションを実行できます
    • 非常に正確
  3. 組み合わせ前の2の[]
    • それは通常1.の処理効率と2の何かをする正確さ+能力を兼ね備えています。

1.の場合 - C#でゆったりと待っている:

Thread.Sleep(numberOfMilliseconds);

ただし、WindowsスレッドスケジューラではSleep()の精度は約15ミリ秒になります(したがって、1ミリ秒だけ待機するようにスケジュールされていても、スリープは簡単に20ミリ秒間待つことができます)。

2.の場合 - C#でのタイトな待機は:

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

DateTime.Nowやその他の時間測定手段を使用することもできますが、Stopwatchははるかに高速です(これは実際には厳密なループで表示されるようになります)。

.の場合 - 組み合わせ:

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の更新、イベントの処理、または対話/通信関連の処理など)の間で実行できます。

146
Thetam

Windowsでは、正確なスリープ時間を指定することはできません。そのためにはリアルタイムOSが必要です。最善の方法は、最小スリープ時間を指定することです。それからそれ以降あなたのスレッドを起こすのはスケジューラ次第です。そして決して GUIスレッドで.Sleep()を呼び出します。

54
Joel Coehoorn

今からあなたは非同期/待機機能を持っています、50msの間眠る最も良い方法はTask.Delayを使うことです:

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

.NET 4をターゲットにしている場合(VS2010またはMicrosoft.Bcl.Async用の非同期CTP 3を使用)は、次のものを使用する必要があります。

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

こうすればUIスレッドをブロックすることはありません。

44
Toni Petrina

このコードを使う

using System.Threading;
// ...
Thread.Sleep(50);
31
Thread.Sleep(50);

指定された時間の間、スレッドはオペレーティングシステムによる実行をスケジュールされません。このメソッドは、WaitSleepJoinを含むようにスレッドの状態を変更します。

このメソッドは、標準のCOMおよびSendMessageポンピングを実行しません。 STAThreadAttributeを持つスレッドでスリープする必要があるが、標準のCOMおよびSendMessageポンピングを実行したい場合は、タイムアウト間隔を指定するJoinメソッドのオーバーロードの1つを使用することを検討してください。

Thread.Join
14
SelvirK
Thread.Sleep
10
Roger Lipscombe

読みやすくするために:

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

.NET Framework 4.5以降では、次を使用できます。

using System.Threading.Tasks;

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

両方の長所:

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);
    }
0
Akumaburn