带有代表的计时器类 C#

问题描述 投票:0回答:2

我需要实现

Timer
类来模拟倒计时时钟。计时器能够向订阅事件的其他类型发送带有有关
Started
Tick
Stopped
事件信息的消息。我无法使用 .NET System.Timer 类来实现此实现。
Timer
类应具有以下功能: - 当构造
Timer
类的对象时,必须对其进行赋值: - 名称(不能为 null 或空字符串,否则应抛出异常
ArgumentException
); - 刻度数(该数字必须大于 0;否则,应抛出异常
ArgumentException
)。 - 创建计时器后,应调用它来运行。为了响应 Run,计时器会触发
Started
事件。该事件应包含有关计时器名称和要触发的滴答数的信息。 - 触发
Started
事件后,计时器开始触发
Tick
事件,其中包含有关计时器名称和剩余触发时间的信息。
Tick
事件之间应该有延迟。要模拟
Tick
事件之间的延迟,建议使用
Thread.Sleep
方法。 - 在所有
Tick
事件被触发后,定时器必须触发
Stopped
事件,该事件应包含定时器的名称信息。

public class Timer
{
    private string name;
    private int numberOfTicks;

    public Timer(string name, int numberOfTicks)
    {
        this.Name = name;
        this.NumberOfTicks = numberOfTicks;
    }

    public event Action<string, int> Tick;

    public event Action<string> Ticks;

    public void OnStarted(Action<string, int> startDelegate)
    {
        this.Tick = startDelegate;
        startDelegate?.Invoke(this.Name, this.NumberOfTicks);
    }

    public void OnStopped(Action<string> stopDelegate)
    {
        this.Ticks = stopDelegate;
        stopDelegate?.Invoke(this.Name);
    }

    public void OnTick(Action<string, int> tickDelegate)
    {
        this.Tick = tickDelegate;
        tickDelegate?.Invoke(this.Name, this.NumberOfTicks - 1);
    }

    public string Name
    {
        get => this.name;

        set
        {
            this.name = value;
            if (value == null || value.Length == 0)
            {
                throw new ArgumentException("Name is empty or null.", nameof(this.Name));
            }
        }
    }

    public int NumberOfTicks
    {
        get => this.numberOfTicks;
        set
        {
            this.numberOfTicks = value;
            if (value <= 0)
            {
                throw new ArgumentException("Number of ticks is less than zero.", nameof(this.NumberOfTicks));
            }
        }
    }
}



public class TimerFactory
{
    /// <summary>
    /// Create an object of the <see cref="Timer"/> class.
    /// </summary>
    /// <param name="name">Name of timer.</param>
    /// <param name="ticks">Count of ticks.</param>
    /// <returns>A reference to an object of the <see cref="Timer"/> class.</returns>
    public Timer CreateTimer(string name, int ticks)
    {
        Timer timer = new Timer(name, ticks);
        return timer;
    }
}

public class CountDownNotifier : ICountDownNotifier
{
    private Timer timer;

    /// <inheritdoc/>
    public void Init(Action<string, int> startDelegate, Action<string> stopDelegate, Action<string, int> tickDelegate)
    {
        this.timer.OnStarted(startDelegate);
        this.timer.OnStopped(stopDelegate);
        this.timer.OnTick(tickDelegate);
    }

    /// <inheritdoc/>
    public void Run()
    {
    }
}

public class CountDownNotifierFactory
{
    /// <summary>
    /// Create an object of the class that implements the <see cref="ICountDownNotifier"/> interface.
    /// </summary>
    /// <param name="timer">A reference to a class CustomTimer.</param>
    /// <returns>A reference to an object of the class that implements the <see cref="ICountDownNotifier"/> interface.</returns>
    /// <exception cref="ArgumentNullException">When timer is null.</exception>
    public ICountDownNotifier CreateNotifierForTimer(Timer timer)
    {
        if (timer == null)
        {
            throw new ArgumentNullException(nameof(timer));
        }

    }
}

我对这项任务有疑问。我不知道如何纠正它。谢谢您的帮助。

c# .net
2个回答
0
投票

在这里,我为您创建了

Timer
小班。我没有处理异常和其他事情,你会做的。我实现了多种创建计时器的方法。

要使用计时器,请编写:

Timer timer = new Timer("Some Name", 100, TimeSpan.FromSeconds(1));
timer.Started += OnTimerStarted;
timer.Tick += OnTimerTick;
timer.Stopped += OnTimerStopped;
timer.Start();

private void OnTimerStarted()
{
}
private void OnTimerTick()
{
}
private void OnTimerStopped()
{
}

Timer timer = new Timer("Some Name", 100, TimeSpan.FromSeconds(1), OnTimerStarted, OnTimerTick, OnTimerStopped); // This one will start timer immediately

Timer timer = Timer.Run("Some Name", 100, TimeSpan.FromSeconds(1), OnTimerStarted, OnTimerTick, OnTimerStopped); // This one will start timer immediately
public class Timer
{
    #region Delegtes Definition
    public delegate void OnStarted();
    public delegate void OnTick();
    public delegate void OnStopped();
    #endregion

    #region Delegates
    public OnStarted? Started { get; set; }
    public OnTick? Tick { get; set; }
    public OnStopped? Stopped { get; set; }
    #endregion

    #region Properties
    private string _name { get; set; }
    private int _nTicks { get; set; }
    private TimeSpan _tickTimeout { get; set; }
    private DateTime _lastTick { get; set; } = DateTime.Now;
    private bool __forceStop { get; set; } = false;
    private bool _forceStop
    {
        get
        {
            return __forceStop;
        }
        set
        {
            if (value == true)
                if (Stopped != null)
                    Stopped();

            __forceStop = true;
        }
    }
    private bool _started { get; set; } = false;
    public string Name { get { return _name; } }
    public int NumberOfTicks { get { return _nTicks; } }
    public TimeSpan TickTimeout { get { return _tickTimeout;} }
    #endregion

    public Timer(string name, int numberOfTicks, TimeSpan tickTimeout)
    {
        _name = name;
        _nTicks = numberOfTicks;
        _tickTimeout = tickTimeout;
    }
    public Timer(string name, int numberOfTicks, TimeSpan tickTimeout, OnStarted startedHandler, OnTick tickHandler, OnStopped stopHanlder, bool autoStart = true)
    {
        _name = name;
        _nTicks = numberOfTicks;
        _tickTimeout = tickTimeout;
        Started += startedHandler;
        Tick += tickHandler;
        Stopped += stopHanlder;

        if (autoStart)
            Start();
    }

    public void Start()
    {
        if (_started)
            throw new Exception("Already started!");

        _started = true;

        Task.Run(() =>
        {
            // Running this delegate on separate thread so I do not stop tick for code inside to execute
            if (Started != null)
                Started();
        });

        Task.Run(() =>
        {
            _lastTick = DateTime.Now;
            while (!_forceStop)
            {
                while (_lastTick.Add(_tickTimeout) > DateTime.Now)
                {
                    if (_forceStop)
                        return;

                    Thread.Sleep(1);
                }

                Task.Run(() =>
                {
                    // Running this delegate on separate thread so I do not stop tick for code inside to execute
                    if (Tick != null)
                        Tick();

                });
                _lastTick = DateTime.Now;
            }
        });
    }
    public void Stop()
    {
        _forceStop = true;
    }
    public Timer Run(string name, int numberOfTicks, TimeSpan tickTimeout, OnStarted startedHandler, OnTick tickHandler, OnStopped stopHanlder)
    {
        return new Timer(name, numberOfTicks, tickTimeout, startedHandler, tickHandler, stopHanlder);
    }
}


0
投票

同样的任务?你设法解决它了吗?我现在真的需要帮助..

© www.soinside.com 2019 - 2024. All rights reserved.