c#窗体计时器不会停止

c#窗体计时器不会停止,c#,C#,我有一个WinForms应用程序,它每秒增加一次计时器并更新标签的文本。 第二个计时器每20毫秒递增一次,以查找最近的鼠标移动,并将当前坐标写入另一个标签 当程序收到Alt+F4时,我实例化“MessageBoxQueryClose”,要求用户关闭或恢复操作。在MessageBox显示之前,我想停止 计时器每秒启动一次,并在用户说“请继续”后重新启用它 这就是我观察到一些“奇怪”行为的地方:每秒一次的计时器再次启动 当MessageBox打开并移动鼠标时 表格代码: using System;

我有一个WinForms应用程序,它每秒增加一次计时器并更新标签的文本。 第二个计时器每20毫秒递增一次,以查找最近的鼠标移动,并将当前坐标写入另一个标签

当程序收到Alt+F4时,我实例化“MessageBoxQueryClose”,要求用户关闭或恢复操作。在MessageBox显示之前,我想停止 计时器每秒启动一次,并在用户说“请继续”后重新启用它

这就是我观察到一些“奇怪”行为的地方:每秒一次的计时器再次启动 当MessageBox打开并移动鼠标时

表格代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Globalization;


namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private bool _altF4Pressed = false;

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Alt && e.KeyCode == Keys.F4)
                _altF4Pressed = true;
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            // show the MessageBox asking the user if the programm should really exit
            MessageBoxQueryClose msgBoxQC = new MessageBoxQueryClose();
            msgBoxQC.QueryClose(ref _altF4Pressed, ref timer2, ref e);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            timer1.Interval = 20;
            timer1.Enabled = true;

            timer2.Interval = 1000;
            timer2.Enabled = true;
        }


        bool toggle = false;

        private void timer2_Tick(object sender, EventArgs e)
        {
            if (toggle)
                label1.Text = "tick";
            else
                label1.Text = "tack";

            toggle = !toggle;
        }


        Point oldPos, newPos;

        private void timer1_Tick(object sender, EventArgs e)
        {
            newPos = Cursor.Position;
            label2.Text = Convert.ToString(newPos.X + ", " + newPos.Y);

            CompareCursorPosition();

            oldPos = newPos; 
        }

        private void CompareCursorPosition()
        {
            if (oldPos != newPos)
                Display_ResetFallback();
        }

        private void Display_ResetFallback()
        {
            timer2.Stop();
            timer2.Start();
        }
    }
}
MessageBoxQueryClose的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;


namespace WindowsFormsApplication1
{
    class MessageBoxQueryClose
    {
        public void QueryClose(ref bool _altF4Pressed, ref Timer timer, ref FormClosingEventArgs e) 
        {
            if (_altF4Pressed)
            {
                // first, disable timer2 to stop Form1.label1 from being updated 
                timer.Enabled = false;

                if (e.CloseReason == CloseReason.UserClosing)
                {
                    DialogResult res;

                    res = MessageBox.Show("Close program ?", "timers",
                                MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);


                    if (res == DialogResult.Yes)
                    {
                        return;
                    }

                    // if program execution shall continue, re-enable timer2
                    timer.Enabled = true;
                }
                e.Cancel = true;
                _altF4Pressed = false;
            }
        }
    }
}
我有一种直觉,我的问题是关于计时器和线程的,但我最近才开始使用.Net,所以任何见解都值得赞赏


br,Chris

您的
timer1\u Tick
事件调用compareCorSorposition(),它调用Display\u ResetFallback(),再次启动
timer2

因此,在QueryClose()中停止
timer2
,但随后触发
timer1\u勾选
事件,再次启动
timer2

您可以修改Display_ResetFallback()以确保计时器仅在当前运行时重新启动:

if (timer2.Enabled)
{
    timer2.Stop();
    timer2.Start();
}

作为补充说明,我可能会完全摆脱MessageBoxQueryClose类,只需相应地修改
FormClosing
事件:

if (e.CloseReason == CloseReason.UserClosing)
{
    timer2.Stop();

    if (MessageBox.Show("Close program ?", "timers", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.No)
    {
        e.Cancel = true;
        timer2.Start();
    }
}

您的
timer1\u Tick
事件调用CompareCursorPosition(),它调用Display\u ResetFallback(),然后再次启动
timer2

因此,在QueryClose()中停止
timer2
,但随后触发
timer1\u勾选
事件,再次启动
timer2

您可以修改Display_ResetFallback()以确保计时器仅在当前运行时重新启动:

if (timer2.Enabled)
{
    timer2.Stop();
    timer2.Start();
}

作为补充说明,我可能会完全摆脱MessageBoxQueryClose类,只需相应地修改
FormClosing
事件:

if (e.CloseReason == CloseReason.UserClosing)
{
    timer2.Stop();

    if (MessageBox.Show("Close program ?", "timers", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.No)
    {
        e.Cancel = true;
        timer2.Start();
    }
}
你可以试试这个

        timer1.Stop();
        label1.Text = timer1.Enabled == false ?"timer disabled":"timer enabled";
        if (MessageBox.Show("Close program ?", "timers",
              MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.OK)
        {
            //do stuff here if you want
        }
        timer1.Start();
        label1.Text = timer1.Enabled == false ? "timer disabled" : "timer enabled";
只要把这些标签文本给你检查。 此编辑不需要该类

编辑:

只需将我的第一篇帖子放入您的代码中……它为我停止,不需要额外的类,删除了2个点和2个方法(Display_ResetFallback和CompareCursorPosition),但您可以根据需要使用它们(2个点变量),并在计时器1内进行检查。

您可以尝试此

        timer1.Stop();
        label1.Text = timer1.Enabled == false ?"timer disabled":"timer enabled";
        if (MessageBox.Show("Close program ?", "timers",
              MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.OK)
        {
            //do stuff here if you want
        }
        timer1.Start();
        label1.Text = timer1.Enabled == false ? "timer disabled" : "timer enabled";
只要把这些标签文本给你检查。 此编辑不需要该类

编辑:


只需将我的第一篇帖子放入代码中……它为我停止,不需要额外的类,删除了2个点和2个方法(Display_ResetFallback和CompareCursorPosition),但如果需要,您可以使用它们(2个点变量),并在计时器1内进行检查。

关于鼠标移动,在检查鼠标移动的控件中,您应该订阅鼠标移动的控件事件,并在该控件中设置鼠标坐标的标签文本,其中包含鼠标移动的e.X和e.y,在检查鼠标移动的控件中,您应该订阅鼠标移动的控件事件,并在其中使用e.X和e.YThanks Grant设置鼠标坐标的标签文本-您的第一句话启发了我。谢谢Grant-您的第一句话启发了我。