3

我试图让我的程序什么都不做,直到我的计时器滴答两次(总共 2 秒)。我正在使用以下代码,除非我取出 while 语句,否则计时器将不起作用。

timer = 0;
Console.WriteLine("timer start ");
timer1.Start();
while (timer < 2);
Console.WriteLine("timer ends");

private void timer1_Tick(object sender, EventArgs e)
{
    Console.WriteLine(timer);
    timer++;
}
4

2 回答 2

4

You should be using System.Timers.Timer, that will run in a seperate thread, See this MSDN article:

From above link:

System.Windows.Forms.Timer

If you're looking for a metronome, you've come to the wrong place. The timer events raised by this timer class are synchronous with respect to the rest of the code in your Windows Forms app. This means that application code that is executing will never be preempted by an instance of this timer class (assuming you don't call Application.DoEvents).

System.Timers.Timer

The .NET Framework documentation refers to the System.Timers.Timer class as a server-based timer that was designed and optimized for use in multithreaded environments. Instances of this timer class can be safely accessed from multiple threads. Unlike the System.Windows.Forms.Timer, the System.Timers.Timer class will, by default, call your timer event handler on a worker thread obtained from the common language runtime (CLR) thread pool. This means that the code inside your Elapsed event handler must conform to a golden rule of Win32 programming: an instance of a control should never be accessed from any thread other than the thread that was used to instantiate it.

Working Code:

public partial class Form1 : Form
{
    System.Timers.Timer  tmr = new System.Timers.Timer(1000);
    volatile int timer;
    public Form1()
    {
        InitializeComponent();

    }

    private void Form1_Shown(object sender, EventArgs e)
    {
        timer = 0;

        tmr.Elapsed += new System.Timers.ElapsedEventHandler(tmr_Elapsed);
        tmr.Start();
        while (timer < 2) ;
        tmr.Stop();
        Console.WriteLine("timer ends");
    }

    void tmr_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        Console.WriteLine(timer);
        timer++;
    }
}
于 2012-11-10T05:51:55.823 回答
3

不确定您使用的是什么计时器类(这很重要)。假设它是 System.Windows.Forms.Timer 之类的东西,滴答永远不会发生,因为它是在主事件循环上调度的,并且您正在将主事件循环与您的 while 循环捆绑在一起。如果它是一个未绑定到 GUI 的计时器类,则可能由于缺少线程同步而存在内存可见性问题。

我也很好奇为什么是两个滴答声?大概这是简化的代码,而您的 timer_tick 方法实际上正在做一些更有趣的事情?如果没有,你可以只使用 Thread.Sleep(2000)。如果刻度代码做了一些有趣的事情,您可以在刻度方法中处理完成,如下所示:

timer = 0;
Console.WriteLine("timer start ");
timer1.Start();

private void timer1_Tick(object sender, EventArgs e)
{
    Console.WriteLine(timer);
    if (++timer == 2) {
      Console.WriteLine("timer ends");
      // and you probably want a timer1.Stop() in here too
    }
}
于 2012-11-10T05:32:56.727 回答