C# System.Threading.Timer不稳定地触发回调
我编写了一个名为C# System.Threading.Timer不稳定地触发回调,c#,timer,C#,Timer,我编写了一个名为DoubleAnimator的类,它在一段时间内将双精度值从起始值更改为结束值 此类基于System.Threading.Timer来更改和报告值 我注意到,主要是在首次使用时,计时器的回调几乎每秒执行一次,而不是50毫秒 我对回调进行了计时,以了解执行回调的时间是否超过了间隔,但需要0到3毫秒 下面是课堂: /// <summary> /// DoubleAnimator animates a double value from a specified value
DoubleAnimator
的类,它在一段时间内将双精度值从起始值更改为结束值
此类基于System.Threading.Timer来更改和报告值
我注意到,主要是在首次使用时,计时器的回调几乎每秒执行一次,而不是50毫秒
我对回调进行了计时,以了解执行回调的时间是否超过了间隔,但需要0到3毫秒
下面是课堂:
/// <summary>
/// DoubleAnimator animates a double value from a specified value to another one in the specified time-frame
/// </summary>
public class DoubleAnimator : IDisposable, IAnimator
{
#if DEBUG
private readonly Logger _logger;
#endif
private readonly double _startValue;
private readonly double _endValue;
private readonly TimeSpan _duration;
private System.Threading.Timer _timer;
private readonly double _incrementPerAnimation;
private readonly TimeSpan _durationBetweenAnimations;
private double _animatedValue;
public double AnimatedValue
{
get { return _animatedValue; }
}
public DoubleAnimator(double startValue, double endValue,
TimeSpan duration, int numberOfAnimations)
{
if (numberOfAnimations <= 0)
{
throw new InvalidOperationException("Number of animation should be superior to 0");
}
#if DEBUG
_logger = new Logger();
#endif
_startValue = startValue;
_endValue = endValue;
_duration = duration;
_animatedValue = _startValue;
_durationBetweenAnimations = TimeSpan.FromTicks(duration.Ticks / numberOfAnimations);
#if DEBUG
_logger.Debug($"Duration between animations: {_durationBetweenAnimations.TotalMilliseconds}ms. Calcul: {duration.TotalMilliseconds}ms/{numberOfAnimations}");
#endif
_incrementPerAnimation = (_endValue - _startValue) / numberOfAnimations;
}
public void Dispose()
{
_timer?.Dispose();
}
public void Start()
{
if (_timer != null) return;
_timer = new System.Threading.Timer(Animate, null, TimeSpan.Zero, _durationBetweenAnimations);
}
public void Abort()
{
if (_timer == null) return;
_timer.Change(Timeout.Infinite, Timeout.Infinite);
}
private void Animate(object state)
{
#if DEBUG
Stopwatch sw = new Stopwatch();
sw.Start();
#endif
try
{
#if DEBUG
_logger.Debug("Animating...");
#endif
_animatedValue += _incrementPerAnimation;
bool animationFinished = false;
if (_endValue > _startValue)
{
animationFinished = _animatedValue > _endValue;
}
else
{
animationFinished = _animatedValue < _endValue;
}
if (animationFinished)
{
_animatedValue = _endValue;
_timer.Change(Timeout.Infinite, Timeout.Infinite);
OnProgressChanged(_animatedValue); //Useful?
OnCompleted();
}
else
{
#if DEBUG
_logger.Debug($"Notification of progress with value {_animatedValue}");
#endif
OnProgressChanged(_animatedValue);
}
}
finally
{
#if DEBUG
_logger.Debug($"Time for executing Animate: {sw.ElapsedMilliseconds}ms.");
#endif
}
}
public event EventHandler<EventArgs> Completed;
private void OnCompleted()
{
Completed?.Invoke(this, EventArgs.Empty);
}
public event EventHandler<ValueEventArgs> ProgressChanged;
private void OnProgressChanged(double progress)
{
ValueEventArgs arg = new ValueEventArgs(progress);
ProgressChanged?.Invoke(this, arg);
}
}
您可以注意到回调是每秒执行一次,而不是每50毫秒执行一次
你能给我指出我班上的问题吗
编辑:@canton7指出,这个问题是线程池不足问题。另一个对象为每个实例创建了一个线程。线程池创建一个新线程需要时间,在创建一个新线程之前尝试检查一个线程是否完成。计时器通常需要比预期更长的时间。通常情况下,他们花的时间比预期的要长一秒钟左右。。。你能在一个独立的应用程序中复制这个吗?我怀疑您的应用程序中还存在其他问题(尽管我不确定具体是什么问题),我看不出您将持续时间定义为50毫秒的位置。另请参见。我运行了您的代码(仅将记录器实现替换为控制台),但没有接近1秒的间隔,但是,由于计时器不准确,出现了一些错误。台式机不是实时系统。以下是输出:
11:44:28.022 |动画之间的持续时间:50ms。计算:500ms/10 11:44:28.034 |动画。。。11:44:28.035 |值为0.1的进度通知11:44:28.035 |执行动画的时间:0ms。11:44:28.093 |制作动画。。。11:44:28.094 |值为0.2的进度通知11:44:28.094 |执行动画的时间:0ms。11:44:28.143 |动画制作…
@canton7这是我最初的想法,但不准确度似乎约为17毫秒,而我的情况是1000毫秒。我将编辑我的问题,并尝试单独使用该对象,而不更改和完成其他对象events@nkoniishvt例如,可能有另一个计时器正在做一些不好的事情,或者您的线程池可能严重缺少线程,或者……计时器通常比预期的时间长一点。通常情况下,他们花的时间比预期的要长一秒钟左右。。。你能在一个独立的应用程序中复制这个吗?我怀疑您的应用程序中还存在其他问题(尽管我不确定具体是什么问题),我看不出您将持续时间定义为50毫秒的位置。另请参见。我运行了您的代码(仅将记录器实现替换为控制台),但没有接近1秒的间隔,但是,由于计时器不准确,出现了一些错误。台式机不是实时系统。以下是输出:11:44:28.022 |动画之间的持续时间:50ms。计算:500ms/10 11:44:28.034 |动画。。。11:44:28.035 |值为0.1的进度通知11:44:28.035 |执行动画的时间:0ms。11:44:28.093 |制作动画。。。11:44:28.094 |值为0.2的进度通知11:44:28.094 |执行动画的时间:0ms。11:44:28.143 |动画制作…
@canton7这是我最初的想法,但不准确度似乎约为17毫秒,而我的情况是1000毫秒。我将编辑我的问题,并尝试单独使用该对象,而不更改和完成其他对象events@nkoniishvt例如,可能有另一个计时器正在做不好的事情,或者您的线程池可能严重缺乏线程,或者。。。
Debug;06-02-2020 11:23:11.612;;Duration between animations: 50ms. Calcul: 500ms/10
Debug;06-02-2020 11:23:12.215;;Animating...
Debug;06-02-2020 11:23:12.215;;Notification of progress with value 0,1
Debug;06-02-2020 11:23:12.215;;Time for executing Animate: 0ms.
Debug;06-02-2020 11:23:13.214;;Animating...
Debug;06-02-2020 11:23:13.214;;Notification of progress with value 0,2
Debug;06-02-2020 11:23:13.215;;Time for executing Animate: 0ms.
Debug;06-02-2020 11:23:14.213;;Animating...
Debug;06-02-2020 11:23:14.213;;Notification of progress with value 0,3
Debug;06-02-2020 11:23:14.213;;Time for executing Animate: 0ms.
Debug;06-02-2020 11:23:15.213;;Animating...
Debug;06-02-2020 11:23:15.213;;Notification of progress with value 0,4
Debug;06-02-2020 11:23:15.213;;Time for executing Animate: 0ms.
Debug;06-02-2020 11:23:16.215;;Animating...
Debug;06-02-2020 11:23:16.215;;Notification of progress with value 0,5
Debug;06-02-2020 11:23:16.215;;Time for executing Animate: 0ms.
Debug;06-02-2020 11:23:17.215;;Animating...
Debug;06-02-2020 11:23:17.215;;Notification of progress with value 0,6
Debug;06-02-2020 11:23:17.216;;Time for executing Animate: 0ms.
Debug;06-02-2020 11:23:18.215;;Animating...
Debug;06-02-2020 11:23:18.215;;Notification of progress with value 0,7
Debug;06-02-2020 11:23:18.216;;Time for executing Animate: 0ms.
Debug;06-02-2020 11:23:19.215;;Animating...
Debug;06-02-2020 11:23:19.215;;Notification of progress with value 0,8
Debug;06-02-2020 11:23:19.216;;Time for executing Animate: 0ms.
Debug;06-02-2020 11:23:20.213;;Animating...
Debug;06-02-2020 11:23:20.214;;Notification of progress with value 0,9
Debug;06-02-2020 11:23:20.214;;Time for executing Animate: 0ms.
Debug;06-02-2020 11:23:21.214;;Animating...
Debug;06-02-2020 11:23:21.214;;Notification of progress with value 1
Debug;06-02-2020 11:23:21.215;;Time for executing Animate: 0ms.