用的是System.Windows.Form命名空间里的计时器
代码如下:
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
 {
    timer1.Stop();//为什么Stop之后,无法用start启动??
     timer1.Start();
.........
}本来计时器是可以正常工作的,一旦接收到数据,执行了timer1.Stop之后,计时器就无法工作了,即使加入了timer1.Start也不行,谁能告诉我这是为什么啊?如果删除timer1.Stop,计时器是可以正常工作的,这是为哪般啊,难道在接收事件里,timer1.Stop是有效的,但是timer.Start是无效的???PS:我知道用委托是不会出现问题的,只是想知道为什么这样做,会导致stop有效而start无效

解决方案 »

  1.   

    使用这个timer1.Enabled=true开启false关闭
      

  2.   


    试过了,一样的问题,使用了timer1.Enabled=false后,计时器停止工作,再使用timer1.Enabled=true无法开启计时器
    为啥在接收事件里只能停止计时器无法开启计时器呢?
      

  3.   

    private void timer1_Tick(object sender, EventArgs e)
            {
                this.textBox1.Text = DateTime.Now.ToString();
            }        private void button1_Click(object sender, EventArgs e)
            {
                if (this.timer1.Enabled)
                {
                    this.timer1.Enabled = false;
                }
                else
                {
                    this.timer1.Interval = 1000;
                    this.timer1.Enabled = true;
                }
            }
    timer1.Enabled=true开启,false停止,可以的呀;
      

  4.   

    接收数据事件停止时间控件运行。数据处理结束事件或方法是启用,启用的时候用Enabled=true
      

  5.   


    定时器定的是100毫秒的
    经试验,不管串口接收的频率是多高,只要有数据过来,只要第一次执行了timer1.stop,计时器就停止工作了,我想问的是为什么stop会导致计时器停止工作,但是start却无法开启,在程序的其它地方先stop后start是没有问题的,但是在接收事件里怎么写就会出问题。问题已经描述过了,stop有效而start无效
      

  6.   

    我知道这样可以。
    囧,我的问题是,为什么在dataReceived事件里stop有效而start有效,这是有个前提的,在接收事件里
      

  7.   


    都试过了,断点调试也试过了,明明在断点调试里发现timer.enabled为true,计时器就是无法工作呀。
    只要我将接收事件里的timer.stop删除,计时器就可以正常工作,但是加入了stop,哪怕紧接着写start,计时器也无法工作。
    为啥在接收事件里,stop会让计时器停止工作,而start无法开启计时器呢
      

  8.   

    http://social.msdn.microsoft.com/Forums/ro-RO/vbasiczhchs/thread/1e159d8b-8369-4526-9149-e34d09e5d16d
    刚才没理解,需要对你有帮助
      

  9.   


    计时,从发出数据开始计时,超过时间没收到对方的响应就提示超时。
    但现在发现在DataReceived事件里,用stop可以将计时器停止,但是用start无法重启计时器。用ENABELD属性也是一样,false可以关闭,但是true不能开启
      

  10.   

    看了你给的链接,那人遇到的问题跟我一眼个,不过那里的答案也没有解决问题,还是没有解答为什么在dataReceived事件里只能用stop关闭计时器不能用start开启(当然用委托是可以正常关闭和开启的)。不过谢谢啦~
      

  11.   

    汗这两行代码已经够了,我将其它代码全部屏蔽,就这两行,也是同样的问题,在接收事件里,timer1.Stop会将计时器停止,timer1.Start却无法启动计时器。我很奇怪,同样都是没有使用委托,为什么timer1.Stop会生效,而timer1.Start却无法生效呢?还是说这其中有其他冲突我不知道的。
      

  12.   

    假定情况:你的timer设定触发时间1秒,SP_DataReceived如果串口发送了一条数据给你,你停止了timer,然后开启timer,开启timer后,在300毫秒的时候你已经处理完了串口的数据,然后又马上收到一条数据这时候你又停止了timer。timer里面的代码根本没执行的机会,你这是想做什么?
      

  13.   

    而且你这个System.Windows.Form.Timer是基于windows消息循环的,计时不准,容易阻塞UI线程导致不可预知的情况。
      

  14.   

    DataReceived在新线程中执行,本来是不应该能操作Form中Timer的,为什么能关闭咱就不知道了,不过可以解决
    http://www.dotblogs.com.tw/chou/archive/2009/03/20/7614.aspx
      

  15.   


    因为会出现一种情况,我发送数据出去但却没收到对方的答复,而这个时间就是timer的触发时间 ,没收到数据就在tick事件里重新发送数据。
    我自己调试的时候串口只接收了一次数据,不存在你说的情况,但是timer却停止工作。
    可以加下QQ具体讨论下么我的问题已经描述很清楚了,是因为stop生效而start不生效,不是你说的那个时间差问题,因为我调试的时候dataReceived只被触发了一次可以的话加下我Q:980809163,请教下关于TIMER的用法
      

  16.   

    不好意思,我们公司不能上QQ的。首先声明一个全局bool变量,初始化为false,你发送了一条数据后,timer.Enabled=true; 当你收到串口的应答之后,将该bool变量赋值为true,timer中1秒后执行判断该变量的状态就知道你收到应答没有,而且不要用System.Windows.Form.Timer,改换成System.Timers.timer!private System.Timers.Timer timer = new System.Timers.Timer(1000);
    timer1.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
    void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
            {
                if(isRead){
    //收到应答
    }else{
    //没有收到应答
    }
    timer.Enabled=false
            }
      

  17.   


    private System.Timers.Timer timer = new System.Timers.Timer(1000);
    private bool isRead=false; timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);//构造函数中注册事件 void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
             {
                 if(isRead){
     //收到应答
     }else{
     //没有收到应答
     }
     timer.Enabled=false
             } 
    发送指令后马上启用timer,收到应答只要修改isRead的值为true!
      

  18.   


    后面遇到更复杂的我会改用System.Timers.timer,但是我的疑惑还是没有解决
    为什么跨线程,直接timer.stop有效而timer.start无效?我重点想问的是这个
    如何避规这个问题我也知道,用委托就好了,但目前为止还是没有人能告诉我为啥在serialPort的dataReceived事件里,直接写timer.stop会停止计时器,但timer.start无法启动计时器。纠结一遇到串口的问题,CSDN的大神就不见了thank you all the same!
      

  19.   

    这个具体什么原因我也不清楚,你调试的时候,运行到timer.start的时候有没有出现异常(有些东西看vs的输出窗体看看有没有异常,因为有些异常是微软为了保证你的串口不崩溃,已经帮你处理了的)?我们猜测一个这种情况:当你线程中去读取一个空间的值,能正常读取,但是赋值就出现异常了!~具体原因还是要看你的vs调试输出信息!~
      

  20.   

    原因就是你错误的使用了它。
    winform控件不是线程安全的,对多线程环境下的表现和行为不做保证。或许在某些情况下它可以正常工作;或许在另外一些情况下不能正常工作——一切都听天由命,控件自身不在这些方面做任何特殊处理。
    或许在这里不能stop了,在另外一个地方不能start了,在别的什么地方interval又异常了
    换句感觉很厉害的话就是:破坏了它的内部状态打个比方,你把本本往地上一摔,发现不能开机了。原因嘛,反正就是里面什么地方摔坏了,至于究竟哪里的什么摔坏了,那是要拆开检查才知道,每次摔坏的地方不一定一样。
    你要做的事,不是去弄清楚,哦,这次硬盘被摔坏了,下次摔的时候要注意点别又把硬盘摔坏了,而是根本就不要去摔它。下次可能你的确是掌握了技巧没把硬盘摔坏但其他地方又摔坏了。或者,你非要摔,就去弄个摔不坏的本本。非线程安全的函数(类型)占多数,在多线程环境下不加保护的使用都可能出现各种异常状况。应对的方法是,要么以安全的方式使用它们,要么去找对应的线程安全版本。
      

  21.   


    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Drawing.Drawing2D;
    using System.Runtime.InteropServices;
    using System.Threading;namespace WindowsApplication1
    {
        public delegate void MyDelegate(string name);//定义委托    public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
                BtnClick += new MyDelegate(Form1_BtnClick);//注册自定义委托事件
            }
            private event MyDelegate BtnClick;//声明自定义事件        void Form1_BtnClick(string name)
            {
                Thread th = new Thread(new ThreadStart(startTimer));//用线程执行startTimer函数
                th.Start();
            }        
            private void Form1_Load(object sender, EventArgs e)//窗体load事件
            {
                BtnClick("...");
            }        private void timer1_Tick(object sender, EventArgs e)//timer_Tick事件
            {
                Console.WriteLine("111");
            }
            private void startTimer()
            {
                this.timer1.Start();
                this.button1.PerformClick();
            }        private void button1_Click(object sender, EventArgs e)
            {
                MessageBox.Show("......");
            }
        }
    }
    结果运行的时候,startTimer函数内,this.timer1.Start();运行通过!this.button1.PerformClick();抛出跨线程异常!但是注释掉this.button1.PerformClick();的方法,timer也没运行!~
      

  22.   


    我是不是可以这样理解:虽然我跨线程错误的使用了timer1.stop,按理是应该报错的,但是由于某种原因,它被错误的执行了,并且生效了,而timer1.start虽然没有报错,但是它没有生效,虽然我通过断点调试,发现timer.enabled属性变成了true.也许是错误的使用导致timer控件出错,使它无法正常工作?
      

  23.   

    同意31楼的说法,这就是一个跨线程调用timer控件的start方法不运行。如果你想具体弄清楚问题的话,还是先把手上的bug解决掉,然后再有时间研究一下!~
      

  24.   

    看来跨线程对timer进行启动是不行的,但是停止却又可以的,囧我觉得就不应该让timer1.Start()编译通过,编译通过了也没有生效。呵呵,谢谢你,看来不仅仅是在DataReceived事件里,只要跨线程对timer直接操作都是有潜在隐患的
      

  25.   

    timer1.Start();是很定有效的,当计时器开始计时后要过100毫秒才能触发,但是在这段时间内,串口接收事件就触发了,这样还没到计时器触发的时间又相当于重新初始化了下计时器,它又要过100毫秒,这样反复。给你的感觉好像是timer1.Start();没有效果。
      

  26.   

    System.Windows.Form.Timer也是基于windows的消息循环的,运行在UI线程,但是估计它内部是一个特殊实现,所以在线程中能调用成功(个人觉得:但是线程退出后,它内部的消息循环估计也中止了)。所以导致System.Windows.Form.Timer没有被运行!~
      

  27.   

    使用这个timer1.Enabled=true开启false关闭
      

  28.   

    问题很简单啦,你的串口接收开启了一个子线程,在子线程里面调用了主线程的资源,当然不能运行啦。
    建议用Thread