C# 定时器不工作';我不想在它被禁用后重新启动
我正在编写一个简单的C#程序,它尝试使用System.Forms.Timer每隔x秒执行一次操作 tick事件调用一个方法,该方法启动一个新线程并禁用计时器,然后当该线程完成其工作时,它会再次启用计时器,但问题是,现在它在启用后不会滴答作响C# 定时器不工作';我不想在它被禁用后重新启动,c#,multithreading,timer,C#,Multithreading,Timer,我正在编写一个简单的C#程序,它尝试使用System.Forms.Timer每隔x秒执行一次操作 tick事件调用一个方法,该方法启动一个新线程并禁用计时器,然后当该线程完成其工作时,它会再次启用计时器,但问题是,现在它在启用后不会滴答作响 static System.Windows.Forms.Timer testtimer = new System.Windows.Forms.Timer(); static void Main() { testtimer.T
static System.Windows.Forms.Timer testtimer = new System.Windows.Forms.Timer();
static void Main()
{
testtimer.Tick += testtimertick;
testtimer.Interval = 5000;
testtimer.Enabled = true;
testtimer.Start();
while (true)
{
Application.DoEvents(); //Prevents application from exiting
}
}
private static void testtimertick(object sender, System.EventArgs e)
{
testtimer.Enabled = false;
Thread t = new Thread(dostuff);
t.Start();
}
private static void dostuff()
{
//Executes some code
testtimer.Enabled = true; //Re enables the timer but it doesn't work
testtimer.Start();
}
Windows窗体控件不是线程安全的,您应该确保在UI线程上使用它们,例如,请参见不要在没有GUI的情况下使用GUI计时器。不要使用
DoEvents
旋转,因为这样会消耗100%的CPU内核。使用系统.Threading.Timer
。它可以正常工作。您可以使用来做您想做的事情,使用来设置时间和时段,完成工作后重新启动即可
static System.Windows.Forms.Timer testtimer = new System.Windows.Forms.Timer();
static void Main()
{
testtimer.Tick += testtimertick;
testtimer.Interval = 5000;
testtimer.Enabled = true;
while (true)
{
Application.DoEvents(); //Prevents application from exiting
}
}
private static void testtimertick(object sender, System.EventArgs e)
{
Thread t = new Thread(dostuff);
t.Start();
}
private static void dostuff()
{
testtimer.Enabled = false;
//Executes some code
testtimer.Enabled = true; //Re enables the timer but it doesn't work
testtimer.Start();
}
class Program
{
static System.Threading.Timer testtimer;
static void Main(string[] args)
{
testtimer = new System.Threading.Timer(testtimertick);
testtimer.Change(5000,0);
Console.ReadLine();
}
private static void testtimertick(object sender)
{
Thread t = new Thread(dostuff);
t.Start();
}
private static void dostuff()
{
//Executes some code
Thread.Sleep(2000);
Console.WriteLine("Tick");
testtimer.Change(5000, 0);
}
}
,您的问题似乎与以下事实有关:您正在对在不同线程上创建的Windows窗体控件进行跨线程调用
如果您使用的是.NET4.5(C#5.0),我建议您查看,可以在
关于如何使用async和Wait处理遗留“DoStuff”的示例:
注意事项:
当使用这些关键字时,DoStuff将异步运行,一旦DoStuff返回,它将使用最初调用Tick的线程的上下文在wait之后继续运行 我刚才也有类似的问题。我正在禁用计时器,并在需要时再次启用。 下次启用时,它将不起作用 当我想禁用计时器对象时,我试着处理它,并在每次我想启用它时创建它的新实例。但是没用 然后想出了一个解决办法。我正在删除testtimer.Tick中配置的事件,然后在需要启用计时器时将其添加回 因此,计时器内部将始终使用有效值实例化,并使其属性Enabled=true。唯一的区别是,每当触发勾号事件时,它实际上不会执行任何操作
这将模拟禁用和启用计时器,并使其与您控制的一样工作,如Enabled=false/true。如果您真的想坚持使用GUI计时器,并从非UI线程启动它,您可以尝试执行类似的操作,然后从非UI线程写入GUI 我知道这不是理想的解决办法
this.Invoke((MethodInvoker)delegate
{
refreshTimer.Enabled = true;
refreshTimer.Start();
});
只是为了确认你在这里的意图;您希望计时器触发,然后在
dostuff()
方法完成之前不触发?是的,确切地说,计时器不应该在dostuff未完成时启动。您是否尝试过timer.Stop()
,然后在其准备就绪时再尝试timer.start()
?我也不太确定计时器是否是线程安全类,所以请检查testTimer.Enabled=true;相当于testTimer.start();请看:我假设您指的是我没有使用线程计时器的事实……我只是坚持OPs实现,尽管我同意使用线程计时器更好,但我认为您希望将0更改为Timeout.Infinite
。即testtimer.Change(5000,Timeout.Infinite)代码>参见@JimMischel实际上根据文档,它们都做相同的事情。如果period为零(0)或无穷大,且dueTime不是无穷大,则回调方法调用一次;计时器的周期行为已禁用,但可以通过调用Change并为period from指定正值来重新启用
this.Invoke((MethodInvoker)delegate
{
refreshTimer.Enabled = true;
refreshTimer.Start();
});