我有一个简单的C#程序(在MS visual Studio 2010中完成)。 它是一个窗口形式,上面有一个按钮。正如你可以看到它只是一个简单的程序,但我坚持它。 我试图在C#中理解C#定时器和全局变量。
按下按钮时,我希望它执行以下操作
出现一个消息框(每秒一次)显示该号码
按下按钮后的秒数。
它应该通过将变量starttimer
设置为true(在一个函数中)以及在检测到starttimer
等于true时在另一个函数中工作,它在消息框中显示以秒为单位的时间。
然而,它似乎没有检测到starttimer
在另一个函数中等于true。 starttimer 变量的目的是检测按下按钮,以便每秒开始显示消息框。
那么修复这个程序最简单的方法是什么?
PS当程序在没有starttimer
代码的情况下运行时,它会每秒显示一个消息框(程序启动时)。
显示程序窗口窗体的图片 - 您可以看到它非常简单 - 只需一个按钮。
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;
}
}
}
答案 0 :(得分:2)
那么修复这个程序最简单的方法是什么?
实际上是按下按钮,因此变量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 (starttimer == true)
的if子句实际上不是必需的,因为您从不在代码中的其他位置调用此方法。
将布尔变量设置为true会使不启动计时器。这只是一面旗帜!
答案 1 :(得分:0)
定时器可能有点奇怪,但看起来你的主要问题是mytimer
在方法范围内,这意味着当该方法结束时,垃圾收集器会清除mytimer
并且它停止运行。发生这种情况是因为当方法结束时,无法再从代码中的其他位置访问mytimer
。为了节省内存,.NET会在你之后清理,但在这种特殊情况下,它并不够聪明,知道你实际上还在使用计时器。
解决方案非常简单,将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();
}
}
}
哦,关于整个'范围'事情。在C#中,范围基本上介于{和}之间。在方法和普通代码中,范围外的代码无法看到范围内创建的变量。这就是为什么如果你执行以下操作会出现编译器错误的原因:
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
类中的所有方法都可以看到类范围内的任何内容,这就是定时器现在可以使用的原因。类范围略有不同,因为如果它们在它们之前公开,你可以在其他类中看到它们。方法也是如此(请注意,您的所有方法都有'私有',因此外部课程无法调用它们。将它们更改为公共,他们可以!)
答案 2 :(得分:-3)
需要启用计时器。
myTimer.Enabled = true