C#使用定时器生成延迟

时间:2017-03-17 16:51:10

标签: c# timer delay

我正在尝试使用Timer在代码中产生延迟。间隔是10毫秒,我的经验函数是timer1_Tick。计时器启动,这些是我的功能:

    private void timer1_Tick(object sender, EventArgs e)
    {
        if (delay_ms != 0) 
        {
            delay_ms--;
        }
    }
    void Timer_Delay(uint delay)
    {
        delay_ms = delay;
        while (delay_ms != 0) ;
    }

我的timer1_Tick工作正常(已测试),但在Timer_Delay函数中,代码会在while (delay_ms != 0) ;行中挂起。它应该在Timer_Delay(100)右边1秒后通过这条线? 以下是使用Timer延迟而不是Thread.sleep

的示例
if (ROTOR_TIME_CONSTANT.BackColor.Equals(Color.Thistle))
            {
                do
                {
                    serialPort.Write("vA" + ROTOR_TIME_CONSTANT.Value + "*");
                    //System.Threading.Thread.Sleep(20);
                    Timer_Delay(100);
                } while (ROTOR_TIME_CONSTANT.BackColor.Equals(Color.Thistle));

5 个答案:

答案 0 :(得分:2)

请改用Thread.Sleep(delayInMilliseconds)。查看文档here

更新

如果您想使用计时器,可以使用EventWaitHandle

    EventWaitHandle ewh;
    uint delay_ms;
    private void timer1_Tick(object sender, EventArgs e)
    {
        if (delay_ms != 0)
        {
            delay_ms--;

            if(delay_ms == 0)
            {
                ewh.Set();
            }
        }
    }
    void Timer_Delay(uint delay)
    {
        ewh = new EventWaitHandle(false, EventResetMode.ManualReset);
        delay_ms = delay;
        ewh.WaitOne();
    }

更新2

这在使用System.Windows.Forms.Timer的WinForms环境中不起作用,因为它在UI的同一个线程上运行。因此,如果您阻止UI的线程,您的计时器将永远不会打勾。如果您仍想使用计时器,则可以使用System.Timers.Timer,这更准确并且在单独的线程上运行,但这样您就会阻止UI,直到延迟过去,因为您正在阻止其线程。
如果您需要等待,您可以先创建一个单独的线程并在那里运行您的进程,因此如果您暂停该线程,UI将保持响应。

答案 1 :(得分:1)

在UI线程上引发了计时器的tick事件。您正在使用无限循环阻止UI线程:

while (delay_ms != 0)

所以Timer永远不会打勾。

答案 2 :(得分:0)

如果您想暂时停止计时器并重新启动计时器,可以考虑以下事项:

async Task Timer_Delay(uint delay)
{
    timer.Stop();
    await System.Threading.Tasks.Task.Delay(delay);
    timer.Start();
}

您可以使用以下方法从异步方法调用此方法:

await Timer_Delay(5000);

修改
从声明为await Timer_Delay(5000);的方法中使用async将执行您指定的许多毫秒(在本例中为5000)但不会与Thread.Sleep具有相同的效果阻止主线程。
这将在从调用的方法中暂停执行,直到计时器再次启动(如上面的Timer_Delay方法所示。

答案 3 :(得分:0)

如果我理解你,你可以使用Timer类。

 public Timer(TimerCallback callback, object state, int dueTime, int period);

例如:

class Program
{
    static void Main(string[] args)
    {
        //Where Hello is a callback, null will be send as an argument to Hello method
        //2000 is a delay in milliseconds, Timeout.Infinite is periodic of calling a method
        Timer timer = new Timer(Hello, null, 2000,Timeout.Infinite);
        Console.ReadKey();
    }

    static void Hello(Object o)
    {
        Console.WriteLine("Hello World");
    }
}

有关详细信息,请参阅此主题:https://msdn.microsoft.com/ru-ru/library/system.threading.timer%28v=vs.110%29.aspx

答案 4 :(得分:-1)

Kordik得到了相关的帖子。你在UI中有一个线程,当它正在流失时,会破坏你的计时器滴答。拿这个简单的代码:

int x = 0;
private void timer1_Tick(object sender, EventArgs e)
{
    x++;
    textBox1.Text = x.ToString();
}

private void button1_Click(object sender, EventArgs e)
{
    DateTime start = DateTime.Now;

    while ((DateTime.Now - start).TotalSeconds < 4)
    {
        System.Threading.Thread.Sleep(10);
    }
}

...当您点击该按钮时,计时器将停止熄灭四秒钟(并且它也不会追溯性地触发事件。)

通过安排异步等待和类似的东西,而不是解决这个问题?让GUI启动一个单独的线程进行处理。无论用户交互或系统事件是什么,或者什么启动这个BackColor检查的整个大功能?让它在一个单独的线程中启动,你绕过了这个问题(以及各种其他问题,如无响应。)

...或者失败,在主循环中包含各种Application.DoEvents()。这将让UI线程仍然继续处理tick事件。 (在我的示例中,在System.Threading.Thread.Sleep(10)旁边添加Application.DoEvents()将使计时器继续工作。