タイマーを使用してアクションの進行状況を計算していますが、実行中のタスクが多いとタイマーが遅れます。
以下は私のタイマークラスです:
public class TimingAction
{
private const int ProgressUpdateIntervalDefault = 500;
public int Duration { get; set; }
public int ProgressUpdateInterval { get; set; }
public event Action<double> ProgressUpdated;
private readonly Timer progressTimer = new Timer();
private readonly Timer scanTimer = new Timer();
private readonly Stopwatch timeWatch = new Stopwatch();
public TimingAction()
{
ProgressUpdateInterval = ProgressUpdateIntervalDefault;
}
public void Start()
{
// Stop progress after duration time
timeWatch.Restart();
scanTimer.Interval = Duration;
scanTimer.Elapsed += (o, e) => Stop();
// Send progress notification
progressTimer.Interval = ProgressUpdateInterval;
progressTimer.Elapsed += (o, e) =>
{
if (ProgressUpdated != null)
{
ProgressUpdated((double)timeWatch.ElapsedMilliseconds / Duration);
}
};
timeWatch.Start();
scanTimer.Start();
progressTimer.Start();
}
public void Stop()
{
scanTimer.Stop();
progressTimer.Stop();
timeWatch.Stop();
}
}
以下は私のテストクラスです:
class Program
{
static void Main(string[] args)
{
int wt, ct;
ThreadPool.GetAvailableThreads(out wt, out ct);
Console.WriteLine("Before starting tasks : worker thread {0}, completion thread {1}", wt, ct);
for (int i = 0; i < 5; i++)
{
int taskID = i;
//Task.Factory.StartNew(() => TestTask(taskID));
var t = new Thread(() => TestTask(taskID));
t.Start();
}
ThreadPool.GetAvailableThreads(out wt, out ct);
Console.WriteLine("After starting tasks : worker thread {0}, completion thread {1}", wt, ct);
var action = new TimingAction();
action.ProgressUpdated += action_ProgressUpdated;
action.ProgressUpdateInterval = 100;
action.Duration = 1000;
action.Start();
Console.WriteLine("After starting timer : worker thread {0}, completion thread {1}", wt, ct);
Console.ReadLine();
}
static void action_ProgressUpdated(double obj)
{
Console.WriteLine("progress {0:00}%", obj*100);
}
static void TestTask(int taskID)
{
while (true)
{
Thread.Sleep(1000);
//Console.WriteLine("Thread ID: {0}, Task {1}", Thread.CurrentThread.ManagedThreadId, taskID);
}
}
}
Thread クラスを使用して TestTask メソッドを実行すると、進行状況はうまくいき、結果は次のようになります。
Before starting tasks : worker thread 1023, completion thread 1000
After starting tasks : worker thread 1023, completion thread 1000
After starting timer : worker thread 1023, completion thread 1000
progress 16%
progress 21%
progress 33%
progress 44%
progress 54%
progress 65%
progress 76%
progress 87%
progress 98%
しかし、Task クラスを使用して TestTask メソッドを実行すると、タイマー Elapsed 呼び出しが遅延し、結果は次のようになります。
Before starting tasks : worker thread 1023, completion thread 1000
After starting tasks : worker thread 1019, completion thread 1000
After starting timer : worker thread 1019, completion thread 1000
progress 105%
progress 199%
この遅延の理由は何ですか?とにかくそれを解決するには? ただし、遅延は最初の 2 秒でのみ発生します。持続時間を 10 秒に増やすと、2 秒の遅延後に進行がうまく機能します。
アプリケーションは、.Net Framework 4.5 で実行されます。