C#プログラムを50ミリ秒間スリープさせるにはどうすればよいですか。
これは簡単な質問に思えるかもしれませんが、一時的な脳障害の瞬間があります。
System.Threading.Thread.Sleep(50);
ただし、メインのGUIスレッドでこれを実行すると、GUIの更新が妨げられることになります(「鈍い」ように感じます)。
;
を削除してVB.netでも機能するようにするだけです。
(ほぼ)あらゆるプログラミング言語で待つための基本的に3つの選択肢があります。
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の更新、イベントの処理、または対話/通信関連の処理など)の間で実行できます。
Windowsでは、正確なスリープ時間を指定することはできません。そのためにはリアルタイムOSが必要です。最善の方法は、最小スリープ時間を指定することです。それからそれ以降あなたのスレッドを起こすのはスケジューラ次第です。そして決して GUIスレッドで.Sleep()
を呼び出します。
今からあなたは非同期/待機機能を持っています、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スレッドをブロックすることはありません。
このコードを使う
using System.Threading;
// ...
Thread.Sleep(50);
Thread.Sleep(50);
指定された時間の間、スレッドはオペレーティングシステムによる実行をスケジュールされません。このメソッドは、WaitSleepJoinを含むようにスレッドの状態を変更します。
このメソッドは、標準のCOMおよびSendMessageポンピングを実行しません。 STAThreadAttributeを持つスレッドでスリープする必要があるが、標準のCOMおよびSendMessageポンピングを実行したい場合は、タイムアウト間隔を指定するJoinメソッドのオーバーロードの1つを使用することを検討してください。
Thread.Join
Thread.Sleep
読みやすくするために:
using System.Threading;
Thread.Sleep(TimeSpan.FromMilliseconds(50));
.NET Framework 4.5以降では、次を使用できます。
using System.Threading.Tasks;
Task.Delay(50).Wait(); // wait 50ms
両方の長所:
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);
}