私のコンソールプログラムが複数の長いタスクを実行するとします。これらのタスクの合間に、数秒間またはいずれかのキーが押されるまで一時停止したいと思います。(いずれか早い方。)
これらの基準は、それ自体で簡単に確認できますが、組み合わせようとするとうまくいきません。ReadKeyが開始する前にタイミングメカニズムが数秒間一時停止するか、Readkeyが満たされるまでスレッドを完全にブロックします。どうすれば両方の条件を満たすことができますか?
C#4.0でこれを行う1つの方法:
Task.Factory.StartNew(() => Console.ReadKey()).Wait(TimeSpan.FromSeconds(5.0));
これを行う1つの方法は、タイマーをまったく使用しないことです。スレッドをたとえば25ミリ秒スリープさせるループを作成し、Console.KeyAvailable(非ブロッキング)を介してキーが押されたかどうか、またはDateTime.Now()
ループの開始との間の時間がループの開始時刻を超えるまでチェックします。タイムアウト。
ikhの答えから拡張して私は私のカウントダウンが欲しかった
var original = DateTime.Now;
var newTime = original;
var waitTime = 10;
var remainingWaitTime = waitTime;
var lastWaitTime = waitTime.ToString();
var keyRead = false;
Console.Write("Waiting for key press or expiring in " + waitTime);
do
{
keyRead = Console.KeyAvailable;
if (!keyRead)
{
newTime = DateTime.Now;
remainingWaitTime = waitTime - (int) (newTime - original).TotalSeconds;
var newWaitTime = remainingWaitTime.ToString();
if (newWaitTime != lastWaitTime)
{
var backSpaces = new string('\b', lastWaitTime.Length);
var spaces = new string(' ', lastWaitTime.Length);
Console.Write(backSpaces + spaces + backSpaces);
lastWaitTime = newWaitTime;
Console.Write(lastWaitTime);
Thread.Sleep(25);
}
}
} while (remainingWaitTime > 0 && !keyRead);
2つのスレッドを開始します。1つはキー押下をリッスンし、もう1つはしばらく待機します。いずれかが行われない限り、メインスレッドを待機させます。次に続行し、他のスレッドの応答を無視します。:)
このようなもの?
bool IsPaused;
bool IsKeyPaused;
void Pause(){}
void UnPause(){}
void KeyDown(){
if(!IsPaused)
{
IsPaused = true;
IsKeyPaused = true;
Pause();
}
}
void KeyUp(){
if(IsKeyPaused)
{
IsPaused = false;
IsKeyPaused = false;
UnPause();
}
}
void TimerPause(){
if(!IsPaused)
{
IsPaused = true;
Pause();
}
}
void TimerEnd(){
UnPause();
}