Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/267.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# System.Threading.Timer不稳定地触发回调_C#_Timer - Fatal编程技术网

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.