使用Timer,如何循环处理比较耗时,就会出现重入的问题
这种情况下,换成线程就能避免

解决方案 »

  1.   


    private void timer_Tick(object sender, EventArgs e)
    {
        MessageBox.Show("dfgdfgfgf");
        Thread.Sleep(10000); ;
    }如果timer_Tick方法是这样的,弹出对话框之后,休眠10秒钟。但是,单击按钮之后,只弹出一次对话框,要等上一次执行完之后,才弹出第二次。
    如果是能重复进入的话,就应该不停地弹出对话框的啊
      

  2.   


    private void timer_Tick(object sender, EventArgs e)
    {
        MessageBox.Show("dfgdfgfgf");
        Thread.Sleep(10000); ;
    }如果timer_Tick方法是这样的,弹出对话框之后,休眠10秒钟。但是,单击按钮之后,只弹出一次对话框,要等上一次执行完之后,才弹出第二次。
    如果是能重复进入的话,就应该不停地弹出对话框的啊
    timer可重复进入,是说它可以不断向主线程的任务队列放入新的任务(那两行代码)。而主线程自己只能排队执行timer放入的任务。
      

  3.   

    修改一下上面的说法:timer可重复进入,是说它可以不断向主线程的任务队列放入 MessageBox.Show 任务(两行代码中的第一行代码)。
    而主线程自己只能排队执行timer放入的这个任务。
    如果你想让Sleep(10000)也运行在主线程里,想看到“阻塞10秒钟才弹出下一个MessageBox”的效果,你应该写类似这样的代码private void timer_Tick(object sender, EventArgs e)
    {
        this.Dispather.Invoke(......
        {
            MessageBox.Show("dfgdfgfgf");
            Thread.Sleep(10000); ;
        });
    }
    这样,主线程中的任务执行两行代码,主线程被 Sleep 阻塞了,你达到了“卡死”主线程的目的了。
      

  4.   

    用TimeSpan对象获取时间间隔 
     private DateTime G_DateTime_First,//定义两个时间字段
                G_DateTime_Second;
            private void btn_First_Click(object sender, EventArgs e)
            {
                G_DateTime_First = DateTime.Now;//为时间字段赋值
                lab_first.Text = "系统时间:" +//显示时间
                    G_DateTime_First.ToString(
                    "yyyy年M月d日 H时m分s秒 fff毫秒");
            }
            private void btn_Second_Click(object sender, EventArgs e)
            {
                G_DateTime_Second = DateTime.Now;//为时间字段赋值
                lab_second.Text = "系统时间:" +//显示时间
                    G_DateTime_Second.ToString(
                    "yyyy年M月d日 H时m分s秒 fff毫秒");
            }
            private void btn_Result_Click(object sender, EventArgs e)
            {
                TimeSpan P_timespan_temp =//计算两个时间的时间间隔
                    G_DateTime_First > G_DateTime_Second ?
                    G_DateTime_First - G_DateTime_Second :
                    G_DateTime_Second - G_DateTime_First;
                lab_result.Text = string.Format(//显示时间间隔
                    "间隔时间:{0}天{1}时{2}分{3}秒 {4}毫秒", 
                    P_timespan_temp.Days, P_timespan_temp.Hours,
                    P_timespan_temp.Minutes, P_timespan_temp.Seconds,
                    P_timespan_temp.Milliseconds);
            }
      

  5.   

    你可以在timer里放入
    messagebox.show("");
    然后你会看到不断有弹出框弹出所以说timer里其实是另一个线程在执行,并不是阻塞主线程
      

  6.   

    你的意思是,timer_Tick方法其实也是在主线程执行的,是吗?
    13楼说的,timer里其实是另一个线程在执行。
    到底该是主线程,还是另一线程呢?
      

  7.   

    你的意思是,timer_Tick方法其实也是在主线程执行的,是吗?
    13楼说的,timer里其实是另一个线程在执行。
    到底该是主线程,还是另一线程呢?TImer就是开个线程执行任务,#10楼都在#11说明了,需要this.Dispather.Invoke才能把任务委托给主线程
      

  8.   

    可是,MSDN说的:如果 System.Timers.Timer 用于 WPF 应用程序,则值得注意的是 System.Timers.Timer 运行于不同于user interface (UI) 线程的其他线程上。 为了访问user interface (UI) 线程上的对象,需要使用 Invoke 或 BeginInvoke 将操作发布到user interface (UI) 线程的 Dispatcher 上。 使用 DispatcherTimer 而不是使用 System.Timers.Timer 的原因是 DispatcherTimer 与 Dispatcher 运行于相同的线程,并且可以在 DispatcherTimer 上设置 DispatcherPriority。
    我使用的就是DispatcherTimer 而不是Timer啊
      

  9.   

    可是,MSDN说的:如果 System.Timers.Timer 用于 WPF 应用程序,则值得注意的是 System.Timers.Timer 运行于不同于user interface (UI) 线程的其他线程上。 为了访问user interface (UI) 线程上的对象,需要使用 Invoke 或 BeginInvoke 将操作发布到user interface (UI) 线程的 Dispatcher 上。 使用 DispatcherTimer 而不是使用 System.Timers.Timer 的原因是 DispatcherTimer 与 Dispatcher 运行于相同的线程,并且可以在 DispatcherTimer 上设置 DispatcherPriority。
    我使用的就是DispatcherTimer 而不是Timer啊
      

  10.   

    DispatcherTimer 定时器是可以重入的,但是要注意的是,当每次time_ticket被触发时,这个方法是被发送到UI线程的队列中执行,这样就导致UI要一个一个来处理这些消息。所以看起来是一个一个执行的。