只重复一次计时器有限次数

时间:2014-12-11 14:48:42

标签: c# user-interface timer

我正在尝试为电动舞台编写接口。我要做的是创建一个扫描功能,使电机移动一定距离,停止并等待指定的时间,然后再次移动相同的距离。它将重复该过程,直到达到用户指定的总长度。为此,我尝试使用Timer类功能,因为我仍然希望GUI在扫描期间处于活动状态。

我已经知道如何编码但却陷入困境。它会像:

private void btnGo_Click(object sender, EventArgs e) //On click
{
    int i = 0;
    int stop = 15; //number of times I want the motor to stop

    System.Timers.Timer bTimer; //initialise timer
    bTimer = new System.Timers.Timer(waittime); //time I want the motor to wait 

    bTimer.Elapsed += PerformMove;
    bTimer.Enabled = true;

    if(i==stop){bTimer.stop()}
}

private void PerformMove(Object source, ElapsedEventArgs e) //event to move motor
{
     //movemotor
     i++;
}

对C#或计时器不是特别熟悉无疑是导致我混淆的原因。解决这个问题的最佳方法是什么?任何示例代码都会很棒。

如果有人能澄清这些行

bTimer.Elapsed += PerformMove;
bTimer.Enabled = true;

实际上做的也很有用!

编辑(抱歉,我认为这不是关键部分):用户点击GUI中文本框中的按钮时,会定义stop的值。即

int stop = Convert.ToDouble(tbIntervalStops.Text); //grab integer from user input upon button click

2 个答案:

答案 0 :(得分:2)

这将是没有内存泄漏的正确解决方案

private int i = 0;
private int stop = 15; //number of times I want the motor to stop
private Timer bTimer; //initialise timer -> Thats wrong: nothing is INITIALIZED here its just defined

private void btnGo_Click(object sender, EventArgs e) //On click
{
    i = 0;
    stop = Convert.ToInt32(tbIntervalStops.Text); //using int because double is a floating point number like 12.34 and for counting only full numbers will be needed

    bTimer = new System.Timers.Timer(waittime); //time I want the motor to wait + Here the Timer is INITIALIZED

    bTimer.Elapsed += PerformMove; //Adds the Eventhandler, What should be called when the time is over
    bTimer.Enabled = true; //This starts the timer. It enables running like pressing the start button on a stopwatch

}

private void PerformMove(Object source, ElapsedEventArgs e) //event to move motor
{
    //movemotor
    i++;

    if (i == stop) //if stop would be a double here we will have the danger to get not a true because of rounding problems
    {
        bTimer.Stop();
        //now enable the Garbage Collector to remove the Timer instance 
        bTimer.Elapsed -= PerformMove; //This removes the Eventhandler
        bTimer.Dispose(); //This frees all resources held by the Timer instance.  
        bTimer = null; 
    }
}

答案 1 :(得分:0)

或者,您也可以从System.Timers.Timer对象派生并创建一个包含特定于该任务的属性的包装器。在这种情况下,您只需要实例化一个MoveTimer并订阅它的OnPerformMoveEvent。

更新:添加了OnMovesCompletedEvent

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TimerExample
{
    public class MoveTimer : System.Timers.Timer
    {
        public event EventHandler OnPerformMoveEvent = delegate { };

        public event EventHandler OnMovesCompletedEvent = delegate { };

        public MoveTimer()
        {
            Initialize(new TimeSpan(), 0);
        }

        public MoveTimer(TimeSpan wait, int moves)
        {
            this.Initialize(wait, moves);
        }

        private int _i;

        private int _totalmoves;
        public int Moves
        {
            get { return this._totalmoves; }
            set { this._totalmoves = value; }
        }

        private TimeSpan _wait;
        public TimeSpan Wait
        {
            get { return this._wait; }
            set { this._wait = value; }
        }

        private System.Timers.Timer _timer;

        private void Initialize(TimeSpan wait, int moves)
        {
            this._totalmoves = moves;
            this._wait = wait;
            this._timer = new System.Timers.Timer(wait.Milliseconds);
        }

        private void BindComponents()
        {
            this._timer.Elapsed += _timer_Elapsed;
        }

        private void UnBindComponents()
        {
            this._timer.Elapsed -= _timer_Elapsed;
        }

        public void StartTimer()
        {
            this._timer.Enabled = true;
        }

        public void StopTimer()
        {
            this._timer.Enabled = false;
        }

        void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            this._i++;

            if (this.OnPerformMoveEvent != null)
                this.OnPerformMoveEvent(this, EventArgs.Empty);

            if (this._i == this._totalmoves)
            {
                this._timer.Stop();
                this.UnBindComponents();
                this.Dispose();

                if (this.OnMovesCompletedEvent != null)
                    this.OnMovesCompletedEvent(this, EventArgs.Empty);
            }
        }
    }
}

关于用户输入,其中移动或停止的数量以字符串形式提供。我会在MoveTimer对象之外处理它。应始终进行验证。

首先确定该值可以解析为整数。如果没有,抛出异常让用户知道输入输入不正确。

要使用上述内容,可能需要以下内容:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TimerExample
{
    class Program
    {
        static void Main(string[] args)
        {
            //Create move timer that will trigger 15 times, once every 30 seconds.
            MoveTimer moveTimer = new MoveTimer(new TimeSpan(0, 0, 30), 15);

            //Substribe to the move timer events
            moveTimer.OnPerformMoveEvent += moveTimer_OnPerformMoveEvent;
            moveTimer.OnMovesCompletedEvent += moveTimer_OnMovesCompletedEvent;

            //Start the timer
            moveTimer.StartTimer();

            //What happens in between the moves performed?
        }

        static void moveTimer_OnMovesCompletedEvent(object sender, EventArgs e)
        {
            //All the moves have been performed, what would you like to happen? Eg. Beep or tell the user.
        }

        static void moveTimer_OnPerformMoveEvent(object sender, EventArgs e)
        {
            //Timer has lapsed, what needs to be done when a move is requested?
        }
    }
}