c#多线程Timer定时器设计,访问主线程控件

        假设现在我们要实现这样一个功能:我们需要让电机某轴(或几轴)循环往复运动,并每次循环获取电机运动结束位置,记录到csv文件中,每个循环结束后(即到达起点),我们要在textBox上写入循环次数。

        我们有toPoint(axis,point,velocity),waitMotorEnd(axis,timeout);getMotorPos(axis),

killMotor(axis)

 一. 第一种方法是添加一个Timer控件,设置Interval间隔,添加tick事件,在这个事件中编程和调用其他函数,用两个按钮和几个变量控制tick是否开启和关闭。

点评:这种方法简单易行,它可以访问任何控件,但是主线程已经有一个timer控件实时读取电机位置并显示出来,导致主界面在电机运动期间是卡死状态,包括最小化等界面图标均无法选中,因为这个timer控件本质上是主线程上的

二. 通过 system.Timers使用系统timer,这种方法不用在界面上拖拽控件,相应的需要在代码中设置属性。

        首先我们先考虑主循环的事件处理,然后再考虑主线程控件调用问题,因为是线程安全的,这个线程是不能直接读取主线程中的控件,需要启用委托。

代码简单如下,仔细弄明白以便在自己的代码中进行移植。

 

using Systems.Timers;
using System.Threading;
namespace demo_np
{
    public partial class MainForm : Form
    {
        private int count_cycle=0;       //循环次数要填入textBox中,全局变量。
        private string path = @"D:\MOTOR_CSV\info.csv";//写入csv的目录,文件在代码中建立。
        
        public MainForm()
		{
			InitializeComponent();
        }
        
        private void Form1_Load(object sender, EventArgs e)
		{
            InitTimer();  //这个是我们设置的timer属性初始化函数。
        }

        System.Timers.Timer timer;//实例化一个计时器
        
         private void InitTimer()
         {
             //设置定时间隔,本例较大,因为太小的话代码执行太快,电机还没动起来导致程序总是认为你电机已经循环过。
             int interval = 2000;
             timer = new System.Timers.Timer(interval);
           //设置执行一次(false)还是一直执行(true)
             timer.AutoReset = true;
             timer.Enabled = false;
            //绑定Elapsed事件,让计时器能够不断执行这个TimerCycle事件
             timer.Elapsed += new System.Timers.ElapsedEventHandler(TimerCycle);
         }

        private void TimerCycle(object sender, System.Timers.ElapsedEventArgs e)
        {
                try
                {
                    timer.Enabled = false;//这里先关闭计时器,事件结尾再打开
                    int timeout = 1000000;
                    waitMotorEnd(0,timeout);代表0轴
                    write_csv();
                    toPoint(0,100.0f);
                    toPoint(0,0.0f);//代表一个往复循环
                    count_cycle = (count_cycle + 1) % 1000000;
                    //text_count.Text=count_cycle.ToString();非法调用主线程控件。
                    timer.Enabled = true;

                }
                catch(Exception ex)
                {
                    MessageBox.Show(ex.Message, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    System.Diagnostics.Debug.WriteLine(ex.Message);
                }
//接下来是按钮控制开关及写入csv方法
        private void btnCycleStart_Click(object sender, EventArgs e)
        {
            count_cycle=0;
            timer.Enabled = true;
            if (!File.Exists(path))
                File.Create(path).Close();//创建csv文件。
        }
        private void button10_Click(object sender, EventArgs e)
        {
            killMotor(0);
            timer.Enabled = false;
        }
        private void write_csv()
        {
            StreamWriter sw = new StreamWriter(path, true, Encoding.UTF8);
            sw.Write("\r\n");
            sw.Write(String.Format("{0:0.0000}", getMotorPos(0) + ",");
            sw.Write(String.Format("{0:0.0000}", getMotorPos(0)) + ",");
            sw.Flush();
            sw.Close();
        }
    }
}

上述代码非法调用控件,接下来通过委托实现访问,注意和上面代码对照需要加到哪里?

delegate void text_countDelegate();
private void text_count()
        {
            this.text_count.Text = cycle_count.ToString();
        }

//这里只是定义了这个委托,名字叫text_countDelegate,既没有运行也没有和咱们这个textcount事件联系起来,那怎么办呢?

 textBox4.Invoke((txb4countDelegate)txb4count);

我们需要将这行代码加到TimerCycle非法调用那里,就可以成功访问啦

 上面这种多线程访问控件的方法好处是可以选择加参数,但是这个例子中并没有参数传递,c#给了我们这样一种方法,MethodInvoker,表示一个委托,该委托可以执行托管代码中(声明为void且不接受任何参数的)任何方法!

this.Invoke((MethodInvoker)delegate
            {
                textCount.Text=cycle_count.ToString();
            }

欢迎任何评论,有不当的地方欢迎提出来,共同交流共同进步!

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值