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 变量,这将完美地解释所描述的行为。否则,它应该可以工作。