環境は.net6.0 C#です。
一定間隔で繰り返し何かをしたいときの書き方をまとめてみます。
まずは、適当に1秒間隔くらいでいい時。
while (true)
{
DoSomething();
await Task.Delay(TimeSpan.FromSeconds(1));
}
これで、ループ事に1秒待って実行されます。
さて、なぜ「適当に」なのか。一応説明しておきます。
DoSomethingの実行に、仮に100ミリかかるとします。
1回目の実行を、0秒の時点だとして、次の実行は、0秒+100ミリ秒+1秒で、1.1秒後になります。
DoSomething()の実行時間分、ずるずる遅れていきます。
で次は、正確に1秒間隔で実行したいときです。
DateTime runNext = DateTime.Now;
while (true)
{
DoSomething();
runNext = runNext + TimeSpan.FromSeconds(1);
var waitTimeSpan = runNext - DateTime.Now;
if (waitTimeSpan > TimeSpan.Zero)
{
await Task.Delay(waitTimeSpan);
}
}
ちょっと面倒になりましたね。
でも、これで1秒毎に実行されるようになります。
DoSomething()に、1秒以上かかるとうまくいかないので、そちらはご注意ください。
おまけで、毎分0秒になったら実行したいというのも書いてみましょう。
// 初回実行は、30秒以上後
// AddSeconds(60)は、秒を切り捨てるので、今より早い時間にならないために。
DateTime tempDateTime = DateTime.Now.AddSeconds(30).AddSeconds(60);
DateTime runNext = new DateTime(tempDateTime.Year, tempDateTime.Month, tempDateTime.Day, tempDateTime.Hour, tempDateTime.Minute, 0);
while(true)
{
DoSomething();
runNext = runNext + TimeSpan.FromMinutes(1);
var waitTimeSpan = runNext - DateTime.Now;
if (waitTimeSpan > TimeSpan.Zero)
{
await Task.Delay(waitTimeSpan);
}
}
追加:以下で、切り捨てとかの実装を見つけた。
リンク先の実装の方が速くてよさそう。
[C#] DateTime を指定した単位に切り上げ、切り捨て、四捨五入する – ざこノート (dokeep.jp)
1件のコメント