繰り返し処理のTaskのタイムアウトのより良い方法というのは何だろう?
数パターン書いてみて、一番C#らしいのはCancellationTokenSourceを使うやり方だと思いました。
都合があって.NET4.0 C#4.0です。
CancellationTokenSourceを使う
一番それらしい??
var source = new CancellationTokenSource();
//タイムアウトの設定 3秒
source.CancelAfter(3000);
Task t = Task.Factory.StartNew(() =>
{
while(true)
{
source.Token.ThrowIfCancellationRequested();
Thread.Sleep(100);//Task.Delay(100);//Delayが使えればDelayが良いな・・・。
}
}, source.Token);
try
{
t.Wait(source.Token);//OperationCanceledExceptionが発生します。
//t.Wait();//AggregateExceptionが発生します。
}
catch(OperationCanceledException)
{
Console.WriteLine("OperationCanceledExceptionが発生しました。");
}
catch(AggregateException)
{
Console.WriteLine("AggregateExceptionが発生しました。");
}
CancellationTokenSourceを使う (微妙)
これに至る前はこう書きました。
微妙
var source = new CancellationTokenSource();
Task t = Task.Factory.StartNew(() =>
{
while (true)
{
source.Token.ThrowIfCancellationRequested();
Thread.Sleep(100);//Task.Delay(100);//Delayが使えればDelayが良いな・・・。
}
}, source.Token);
try
{
t.Wait(3000, source.Token);
if (!t.IsCompleted)
{
source.Cancel();
t.Wait();
}
}
catch (OperationCanceledException)
{
Console.WriteLine("OperationCanceledExceptionが発生しました。");
}
catch (AggregateException)
{
Console.WriteLine("AggregateExceptionが発生しました。");
}
Waitが2つだったりtry~catchが2箇所を目的に包んでいたり。
ちょっと気持ち悪いですね。
CancellationTokenSourceを使わない
CancellationTokenSourceを使わないと何かしらの手段で自前で時間を測る必要が出てきます。
DateTimeとTimeSpan
Task t = Task.Factory.StartNew(() =>
{
var start = DateTime.Now;
while (true)
{
if(DateTime.Now - start > TimeSpan.FromMilliseconds(3000))
{
break;
}
Thread.Sleep(100);
}
});
t.Wait();
Stopwatch
Task t = Task.Factory.StartNew(() =>
{
var stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
while (true)
{
if(stopwatch.ElapsedMilliseconds > 3000)
{
stopwatch.Stop();
break;
}
Thread.Sleep(100);
}
});
t.Wait();