C# 为什么';定时器不能在程序中启动吗?
我有一个简单的C#程序(在MS visual Studio 2010中完成)。 它是一个windows窗体,上面有一个按钮。正如你所看到的,这只是一个简单的程序,但我仍然坚持下去。 我试图理解C#计时器和C#中的全局变量 当按下按钮时,我希望它执行以下操作 此时(每秒)会出现一个消息框,显示号码 按钮按下后的秒数。 它通过将变量C# 为什么';定时器不能在程序中启动吗?,c#,winforms,C#,Winforms,我有一个简单的C#程序(在MS visual Studio 2010中完成)。 它是一个windows窗体,上面有一个按钮。正如你所看到的,这只是一个简单的程序,但我仍然坚持下去。 我试图理解C#计时器和C#中的全局变量 当按下按钮时,我希望它执行以下操作 此时(每秒)会出现一个消息框,显示号码 按钮按下后的秒数。 它通过将变量starttimer设置为true(在一个函数中)来工作,在另一个函数中,当检测到starttimer等于true时,它会在消息框中以秒为单位显示时间 但是,它似乎没有检
starttimer
设置为true(在一个函数中)来工作,在另一个函数中,当检测到starttimer
等于true时,它会在消息框中以秒为单位显示时间
但是,它似乎没有检测到另一个函数中的starttimer
等于true。starttimer变量的作用是检测用于每秒开始显示消息框的按钮按下情况
那么,修复此程序的最简单方法是什么
PS当程序运行时,如果没有starttimer
的代码,它会每秒显示一次消息框(当程序启动时)
显示了程序windows窗体的图片-正如您所看到的,它非常简单,只需一个按钮
namespace timerprogram
{
public partial class doeverysecond : Form
{
int thetimeinsecs = 0;
bool starttimer = false;
private void Form1_Load(object sender, EventArgs e)
{
}
private void customfn(object source, ElapsedEventArgs e)
{
if (starttimer == true)
{
thetimeinsecs = thetimeinsecs + 1;
MessageBox.Show(thetimeinsecs.ToString());
}
}
public doeverysecond()
{
{
{
System.Timers.Timer mytimer = new System.Timers.Timer();
mytimer.Elapsed += new ElapsedEventHandler(customfn);
mytimer.Interval = 1000;
mytimer.Start();
}
}
}
private void button1_Click(object sender, EventArgs e)
{
starttimer = true;
}
}
}
需要启用计时器
myTimer.Enabled = true
那么,修复此程序的最简单方法是什么
实际上,点击按钮,使变量
starttimer
设置为true
,您将能够每秒看到MessageBox
。你的程序工作
除此之外,最好在程序中加入更多结构,方法是通过单击按钮启动计时器:
private void button1_Click(object sender, EventArgs e)
{
if(!mytimer.Enabled) // this will prevent a double start
{
starttimer = true;
mytimer.Start();
}
}
构造函数应该去掉计时器开始行:
public doeverysecond()
{
{
System.Timers.Timer mytimer = new System.Timers.Timer();
mytimer.Elapsed += new ElapsedEventHandler(customfn);
mytimer.Interval = 1000;
}
}
责任分工在这里很重要。构造函数用于初始化变量。这就是他的工作。这个按钮启动计时器
实际上没有必要使用if子句检查if(starttimer==true)
,因为您从未从代码中的其他地方调用此方法
将布尔变量设置为true不会启动计时器。它只是一面旗帜 计时器可能有点奇怪,但您的主要问题似乎是
mytimer
在一个方法范围内,这意味着当该方法结束时,mytimer
被垃圾收集器清除,并停止运行。这是因为当方法结束时,无法从代码中的其他位置再次访问mytimer
。为了节省内存,.NET会在您之后进行清理,但在这种特殊情况下,它不够聪明,无法知道您实际上仍在使用计时器
myTimer.Enabled = true
解决方案非常简单,将mytimer
放在类级别。您还可以去掉starttimer
bool,因为现在您可以检查计时器本身,查看它是否正在运行
你可以这样做:
namespace timerprogram
{
public partial class doeverysecond : Form
{
//Timer is class level, so it sticks around and can be called from
//multiple methods
System.Timers.Timer mytimer = new System.Timers.Timer();
int thetimeinsecs = 0;
private void Form1_Load(object sender, EventArgs e)
{
//Setup the timer, but don't start it
mytimer.Elapsed += new ElapsedEventHandler(customfn);
mytimer.Interval = 1000;
}
private void customfn(object source, ElapsedEventArgs e)
{
//We can check the timer itself to see if it's running!
if (mytimer.Enabled)
{
thetimeinsecs = thetimeinsecs + 1;
MessageBox.Show(thetimeinsecs.ToString());
}
}
private void button1_Click(object sender, EventArgs e)
{
//Start the timer!
mytimer.Start();
}
}
}
if(something)
{
int x = 5;
}
x = x + 5; //x doesn't exist here! It disappears at }
哦,关于整个“范围”的事情。在C#中,作用域基本上是介于a{和a}之间的东西。在方法和普通代码中,作用域内创建的变量不能被作用域外的代码看到。这就是为什么在执行以下操作时会出现编译器错误:
namespace timerprogram
{
public partial class doeverysecond : Form
{
//Timer is class level, so it sticks around and can be called from
//multiple methods
System.Timers.Timer mytimer = new System.Timers.Timer();
int thetimeinsecs = 0;
private void Form1_Load(object sender, EventArgs e)
{
//Setup the timer, but don't start it
mytimer.Elapsed += new ElapsedEventHandler(customfn);
mytimer.Interval = 1000;
}
private void customfn(object source, ElapsedEventArgs e)
{
//We can check the timer itself to see if it's running!
if (mytimer.Enabled)
{
thetimeinsecs = thetimeinsecs + 1;
MessageBox.Show(thetimeinsecs.ToString());
}
}
private void button1_Click(object sender, EventArgs e)
{
//Start the timer!
mytimer.Start();
}
}
}
if(something)
{
int x = 5;
}
x = x + 5; //x doesn't exist here! It disappears at }
但是,您可以在范围内从范围外访问内容,所以
int x = 0;
if(something)
{
x = 5; //x exists in an outside scope
}
x = x + 5; //This is fine
类作用域中的任何内容都可以被类中的所有方法看到,这就是为什么计时器现在仍然存在的原因。不过类的作用域略有不同,因为如果其他类前面有public,您可以在它们中看到它们。方法也是如此(请注意,您的所有方法都有“private”,因此外部类不能调用它们。将它们更改为public,它们就可以了!)您从不调用DoeverySecond,它是C#,而不是“C Sharp”,并且您不想每次都创建一个新计时器,“mytimer”应该移到类中。格式化您的代码,提问。。。基本上一切都好。此问题在当前状态下不可读。是否设置了断点?你点击按钮点击代码了吗?您是否在customfn中点击了断点?否。
Start()
将启用计时器。该操作名为mytimer.Start()代码>在启用计时器的构造函数中。实际上是点击按钮,这样变量starttimer就被设置为true,您就可以在每秒钟看到MessageBox。你的程序行得通-我仍然没有让它工作-我一定错过了一些简单的东西你的右startimer可以有一个更好的名字-它的目的是在屏幕上显示计时器-一个标志来检测按钮按下你使用的是什么版本的C Sharp?2010年?我使用的是VS 2013和2015。我无法想象他们会在两个版本之间改变计时器的工作方式。您可以将变量设置为代码中的其他位置(未发布的部分),或者只需按下按钮即可。我无法想象一旦事件被注册,if子句实际上就不起作用了。计时器将保留在内存中,直到敌人注销或程序结束。只要事件已注册,垃圾收集器就不会触动计时器。我在原始程序中没有使用Form1_load。Form1_load—从您的代码—只要程序在屏幕上运行,它就会自动被调用,对吗?当表单加载到屏幕/图形内存中时,Form1\u load在开始时不会被调用一次