C# - System.Timers.Timer 不会关闭
C# - System.Timers.Timer will not turn off
我有一个运行在两个计时器(Clock 和 IntervalCounter)上的系统。 Clock 使用滴答事件处理程序在每个滴答(每秒)更新显示,这很简单。 IntervalCounter 使用 'elapsed' 事件处理程序输出一个消息框来告诉用户是时候输入下一组数据了(每 5 分钟一次)。
程序中有一点我希望 intervalCounter 关闭,因为不再需要警报,但无论我如何尝试实现这一点,警报都会继续出现。我试过连接两个定时器,当Clock关闭时,IntervalCounter也关闭,但这似乎没有生效。
初始化和运行计时器事件处理函数的代码如下所示,以及在我希望 IntervalCounter 关闭的位置单击按钮:
'Clock' 函数:
private void initialiseClock() //initialisation of Clock Timer
{
Clock = new System.Windows.Forms.Timer();
Clock.Tick += new EventHandler(Clock_Tick); //calls Clock EventHandler
Clock.Interval = 1000; //1 second in miliseconds
Clock.Start();
}
//initialiseClock sub-functions
private void Clock_Tick(object sender, EventArgs e) //Clock EventHandler definition
{
updateTimeDisplay();
checkDisplay();
}
//end initialiseClock sub-functions
'IntervalCounter' 函数:
private void initialiseIntervalCounter() //initialisation of IntervalCounter Timer
{
System.Timers.Timer intervalCounter = new System.Timers.Timer();
intervalCounter.Elapsed += new ElapsedEventHandler(intervalAlert); //calls intervalCounter EventHandler
intervalCounter.Interval = 300000; //5 minutes in miliseconds
if (Clock.Enabled == true) //set intervalCounter to rely on Clock
{
intervalCounter.Enabled = true; //turn on when Clock is on
intervalCounter.Start();
}
else if (Clock.Enabled == false)
{
intervalCounter.Enabled = false; //turn off when Clock is off
Clock.Stop();
intervalCounter.Stop();
}
}
//initialiseIntervalCounter sub-functions
private void intervalAlert(object source, ElapsedEventArgs e) //intervalCounter EventHandler definition
{
Clock.Enabled = false;
string alertTitle = "Interval Alert";
string alertMessage = "The 5 minute interval has been reached, enter the current readings";
clearInput();
DialogResult okRes = MessageBox.Show(alertMessage, alertTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
if (okRes == DialogResult.OK)
{
Clock.Enabled = true;
}
}
//end initialiseIntervalCounter sub-functions
btnFinish 进程(IntervalCounter 应禁用):
private void btnFinish_Click(object sender, EventArgs e)
{
Clock.Enabled = false; //turn off Clock (and reliant Timers)
string finishmsg = "Save monitoring data and end monitoring"; //message displayed to user
string finishTitle = "End Monitoring Confirmation"; //title of the message box
DialogResult finishRes = MessageBox.Show(finishmsg, finishTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question); //display messageBox and options
if (finishRes == DialogResult.Yes)
{
saveFileFooter(); //append the footer template and associated variable values to the text file
saveBPChartImage();
MessageBox.Show("The vitals data recorded in this program has been saved to the file: " +
fileName + //file name specified
"\nThe recovery data fields can now be filled in"); //give user file address and direct to completing recovery data
enableRecoveryData();
intervalCounter.Stop();
StopWatch = Stopwatch.StartNew();
}
else
{
Clock.Enabled = true;
intervalCounter.Enabled = true;
}
}
关于从这里去哪里的任何建议 class,谢谢!
马克
我发现在 Timer.Elapsed 事件中 documentation:
Even if SynchronizingObject is not null, Elapsed events can occur after the Dispose or Stop method has been called or after the Enabled property has been set to false, because the signal to raise the Elapsed event is always queued for execution on a thread pool thread. One way to resolve this race condition is to set a flag that tells the event handler for the Elapsed event to ignore subsequent events.
也许您应该尝试向 "intervalAlert" 事件处理程序添加一个标志。像这样:
bool alertIsOFF = false; // Global variable
private void btnFinish_Click(object sender, EventArgs e)
{
Clock.Enabled = false; //turn off Clock (and reliant Timers)
string finishmsg = "Save monitoring data and end monitoring"; //message displayed to user
string finishTitle = "End Monitoring Confirmation"; //title of the message box
DialogResult finishRes = MessageBox.Show(finishmsg, finishTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question); //display messageBox and options
if (finishRes == DialogResult.Yes)
{
saveFileFooter(); //append the footer template and associated variable values to the text file
saveBPChartImage();
MessageBox.Show("The vitals data recorded in this program has been saved to the file: " +
fileName + //file name specified
"\nThe recovery data fields can now be filled in"); //give user file address and direct to completing recovery data
enableRecoveryData();
intervalCounter.Stop();
alertIsOff = true;
StopWatch = Stopwatch.StartNew();
}
else
{
Clock.Enabled = true;
intervalCounter.Enabled = true;
}
}
//initialiseIntervalCounter sub-functions
private void intervalAlert(object source, ElapsedEventArgs e) //intervalCounter EventHandler definition
{
if (!alertIsOff)
{
Clock.Enabled = false;
string alertTitle = "Interval Alert";
string alertMessage = "The 5 minute interval has been reached, enter the current readings";
clearInput();
DialogResult okRes = MessageBox.Show(alertMessage, alertTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
if (okRes == DialogResult.OK)
{
Clock.Enabled = true;
}
}
}
//end initialiseIntervalCounter sub-functions
我认为您可能只是犯了一个微不足道的编程错误。如图所示,代码将无法编译,因为您的 intervalConter 是 initialiseIntervalCounter() 中的局部变量。也许您将其单独声明为 class 变量,这将完美地解释所描述的行为。否则,它应该可以工作。
我有一个运行在两个计时器(Clock 和 IntervalCounter)上的系统。 Clock 使用滴答事件处理程序在每个滴答(每秒)更新显示,这很简单。 IntervalCounter 使用 'elapsed' 事件处理程序输出一个消息框来告诉用户是时候输入下一组数据了(每 5 分钟一次)。
程序中有一点我希望 intervalCounter 关闭,因为不再需要警报,但无论我如何尝试实现这一点,警报都会继续出现。我试过连接两个定时器,当Clock关闭时,IntervalCounter也关闭,但这似乎没有生效。
初始化和运行计时器事件处理函数的代码如下所示,以及在我希望 IntervalCounter 关闭的位置单击按钮:
'Clock' 函数:
private void initialiseClock() //initialisation of Clock Timer
{
Clock = new System.Windows.Forms.Timer();
Clock.Tick += new EventHandler(Clock_Tick); //calls Clock EventHandler
Clock.Interval = 1000; //1 second in miliseconds
Clock.Start();
}
//initialiseClock sub-functions
private void Clock_Tick(object sender, EventArgs e) //Clock EventHandler definition
{
updateTimeDisplay();
checkDisplay();
}
//end initialiseClock sub-functions
'IntervalCounter' 函数:
private void initialiseIntervalCounter() //initialisation of IntervalCounter Timer
{
System.Timers.Timer intervalCounter = new System.Timers.Timer();
intervalCounter.Elapsed += new ElapsedEventHandler(intervalAlert); //calls intervalCounter EventHandler
intervalCounter.Interval = 300000; //5 minutes in miliseconds
if (Clock.Enabled == true) //set intervalCounter to rely on Clock
{
intervalCounter.Enabled = true; //turn on when Clock is on
intervalCounter.Start();
}
else if (Clock.Enabled == false)
{
intervalCounter.Enabled = false; //turn off when Clock is off
Clock.Stop();
intervalCounter.Stop();
}
}
//initialiseIntervalCounter sub-functions
private void intervalAlert(object source, ElapsedEventArgs e) //intervalCounter EventHandler definition
{
Clock.Enabled = false;
string alertTitle = "Interval Alert";
string alertMessage = "The 5 minute interval has been reached, enter the current readings";
clearInput();
DialogResult okRes = MessageBox.Show(alertMessage, alertTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
if (okRes == DialogResult.OK)
{
Clock.Enabled = true;
}
}
//end initialiseIntervalCounter sub-functions
btnFinish 进程(IntervalCounter 应禁用):
private void btnFinish_Click(object sender, EventArgs e)
{
Clock.Enabled = false; //turn off Clock (and reliant Timers)
string finishmsg = "Save monitoring data and end monitoring"; //message displayed to user
string finishTitle = "End Monitoring Confirmation"; //title of the message box
DialogResult finishRes = MessageBox.Show(finishmsg, finishTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question); //display messageBox and options
if (finishRes == DialogResult.Yes)
{
saveFileFooter(); //append the footer template and associated variable values to the text file
saveBPChartImage();
MessageBox.Show("The vitals data recorded in this program has been saved to the file: " +
fileName + //file name specified
"\nThe recovery data fields can now be filled in"); //give user file address and direct to completing recovery data
enableRecoveryData();
intervalCounter.Stop();
StopWatch = Stopwatch.StartNew();
}
else
{
Clock.Enabled = true;
intervalCounter.Enabled = true;
}
}
关于从这里去哪里的任何建议 class,谢谢!
马克
我发现在 Timer.Elapsed 事件中 documentation:
Even if SynchronizingObject is not null, Elapsed events can occur after the Dispose or Stop method has been called or after the Enabled property has been set to false, because the signal to raise the Elapsed event is always queued for execution on a thread pool thread. One way to resolve this race condition is to set a flag that tells the event handler for the Elapsed event to ignore subsequent events.
也许您应该尝试向 "intervalAlert" 事件处理程序添加一个标志。像这样:
bool alertIsOFF = false; // Global variable
private void btnFinish_Click(object sender, EventArgs e)
{
Clock.Enabled = false; //turn off Clock (and reliant Timers)
string finishmsg = "Save monitoring data and end monitoring"; //message displayed to user
string finishTitle = "End Monitoring Confirmation"; //title of the message box
DialogResult finishRes = MessageBox.Show(finishmsg, finishTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question); //display messageBox and options
if (finishRes == DialogResult.Yes)
{
saveFileFooter(); //append the footer template and associated variable values to the text file
saveBPChartImage();
MessageBox.Show("The vitals data recorded in this program has been saved to the file: " +
fileName + //file name specified
"\nThe recovery data fields can now be filled in"); //give user file address and direct to completing recovery data
enableRecoveryData();
intervalCounter.Stop();
alertIsOff = true;
StopWatch = Stopwatch.StartNew();
}
else
{
Clock.Enabled = true;
intervalCounter.Enabled = true;
}
}
//initialiseIntervalCounter sub-functions
private void intervalAlert(object source, ElapsedEventArgs e) //intervalCounter EventHandler definition
{
if (!alertIsOff)
{
Clock.Enabled = false;
string alertTitle = "Interval Alert";
string alertMessage = "The 5 minute interval has been reached, enter the current readings";
clearInput();
DialogResult okRes = MessageBox.Show(alertMessage, alertTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
if (okRes == DialogResult.OK)
{
Clock.Enabled = true;
}
}
}
//end initialiseIntervalCounter sub-functions
我认为您可能只是犯了一个微不足道的编程错误。如图所示,代码将无法编译,因为您的 intervalConter 是 initialiseIntervalCounter() 中的局部变量。也许您将其单独声明为 class 变量,这将完美地解释所描述的行为。否则,它应该可以工作。