为什么这个system.threading.timer控件在指定时间不会触发?

时间:2012-10-16 10:00:18

标签: c# multithreading c#-4.0 timer threadpool

好的,我有这个timer控件,当我启动程序时运行正常,但是当我最大化或最小化表单时,计时器控件停止工作。它没有更新任何东西? 这是代码

public MainForm()
        {
            InitializeComponent();
            var tm =
                new System.Threading.Timer(state => statusDateTimeLabel.Text = DateTime.Now.ToLocalTime().ToString(CultureInfo.InvariantCulture), null, TimeSpan.FromMilliseconds(0),
                TimeSpan.FromMilliseconds(1000));                
        }

有时,标签甚至没有更新,有时它会更新。但主要问题是,当我最大化表单时,再次恢复它时,它会停止更新时间。任何人都可以解释我做错了什么?

如果不清楚,我在状态栏中有这个标签控件,我想在该标签中显示当前的日期时间。

认为这可能是因为这个帖子可能正忙于做其他事情,我甚至试过这个

public MainForm()
    {
        InitializeComponent();
        ThreadPool.QueueUserWorkItem(delegate(object state)
                                         {
                                             new System.Threading.Timer(
                                                 stateObj =>
                                                 statusDateTimeLabel.Text =
                                                 DateTime.Now.ToLocalTime().ToString(CultureInfo.InvariantCulture),
                                                 null, TimeSpan.FromMilliseconds(0),
                                                 TimeSpan.FromMilliseconds(1000));
                                         });
    }

但是这又一次与上面相同,有时会更新,有时它不会,令我感到困惑的是,当我最大化表格甚至调整大小时,它会停止更新? 任何人都可以帮我弄清问题是什么?

3 个答案:

答案 0 :(得分:3)

更新文本的回调未在UI线程上执行。请尝试以下方法:

var context = SynchronizationContext.Current;
var tm = new System.Threading.Timer(state => 
{
  context.Send(delegate() { statusDateTimeLabel.Text = DateTime.Now.ToLocalTime().ToString(CultureInfo.InvariantCulture); });
}, null, TimeSpan.FromMilliseconds(0), TimeSpan.FromMilliseconds(1000));

答案 1 :(得分:2)

你没有保持对它的引用,所以在某个时间点,它将被垃圾收集。见Timer

  

只要您使用计时器,就必须保留对它的引用。与任何托管对象一样, Timer 在没有引用时会受到垃圾回收的影响。 计时器仍处于活动状态的事实不会阻止它被收集。

并做:

Timer tm; //Moved to a field

public MainForm()
        {
            InitializeComponent();
            tm =
                new System.Threading.Timer(state => statusDateTimeLabel.Text = DateTime.Now.ToLocalTime().ToString(CultureInfo.InvariantCulture), null, TimeSpan.FromMilliseconds(0),
                TimeSpan.FromMilliseconds(1000));                
        }

(尽管正如其他人所指出的那样,如果您在计时器回调中所做的工作与UI进行交互,那么您可能选择了错误的组件)

答案 2 :(得分:0)

如果您使用的是Windows窗体,则应使用System.Windows.Forms.Timer而不是System.Threading.Timer,如下所示:http://msdn.microsoft.com/en-us/library/system.threading.timer.aspx