C#,WinForms,等待计时器

C#,WinForms,等待计时器,c#,while-loop,mouseevent,system.timers.timer,C#,While Loop,Mouseevent,System.timers.timer,试图理解C#Winforms中的计时器和虚拟点击。我想让程序有一个用户输入的时间值(textbox1),然后等待该时间量并单击鼠标,然后增加数字计数器(textbox2) 在下面的代码中,数字计数器立即变为10,但是点击永远不会结束,尽管有一个while循环设置为在10停止点击。我基本上只是想让程序等待一个稍微随机的时间(输入的时间到输入的时间+3),单击鼠标,增加计数器,然后选择一个新的随机数并继续,直到总共点击10次 public Form1() { Initial

试图理解C#Winforms中的计时器和虚拟点击。我想让程序有一个用户输入的时间值(textbox1),然后等待该时间量并单击鼠标,然后增加数字计数器(textbox2)

在下面的代码中,数字计数器立即变为10,但是点击永远不会结束,尽管有一个while循环设置为在10停止点击。我基本上只是想让程序等待一个稍微随机的时间(输入的时间到输入的时间+3),单击鼠标,增加计数器,然后选择一个新的随机数并继续,直到总共点击10次

 public Form1()
    {
        InitializeComponent();
    }

    private void NumbersOnly(object sender, KeyPressEventArgs e)
    {
        char ch = e.KeyChar;
        if (!Char.IsDigit(ch) && ch != 8)
        {
            e.Handled = true;
        }
    }

    static System.Timers.Timer _timer;
    int numberofclicks = 0;
    [DllImport("user32.dll")]
    static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
    private const int MOUSEEVENTF_MOVE = 0x0001;
    private const int MOUSEEVENTF_LEFTDOWN = 0x0002;
    private const int MOUSEEVENTF_LEFTUP = 0x0004;
    private const int MOUSEEVENTF_RIGHTDOWN = 0x0008;
    private const int MOUSEEVENTF_RIGHTUP = 0x0010;
    private const int MOUSEEVENTF_MIDDLEDOWN = 0x0020;
    private const int MOUSEEVENTF_MIDDLEUP = 0x0040;
    private const int MOUSEEVENTF_ABSOLUTE = 0x8000;


    private void StartClicked(object sender, EventArgs e)
    {
        numberofclicks = 0;
        Random rsn = new Random();

        while (numberofclicks < 10)
        {
            string startseconds = textBox1.Text;
            int timerstartseconds = Convert.ToInt32(startseconds);
            int timertime = rsn.Next(timerstartseconds * 1000, ((timerstartseconds + 3) * 1000));
            _timer = new System.Timers.Timer(timertime);

            _timer.Elapsed += _timer_Elapsed;
            _timer.Enabled = true;

            textBox2.Clear();
            numberofclicks++;
            string numbertextbox = numberofclicks.ToString();
            textBox2.Text = numbertextbox;

        }
    }

    void _timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        LeftClick();                        
    }

    public static void LeftClick()
    {
        mouse_event(MOUSEEVENTF_LEFTDOWN, Control.MousePosition.X, Control.MousePosition.Y, 0, 0);
        mouse_event(MOUSEEVENTF_LEFTUP, Control.MousePosition.X, Control.MousePosition.Y, 0, 0);
    }
public Form1()
{
初始化组件();
}
仅限专用无效号码(对象发送者,按键事件参数e)
{
char ch=e.KeyChar;
如果(!Char.IsDigit(ch)&&ch!=8)
{
e、 已处理=正确;
}
}
静态系统定时器定时器定时器_定时器;
int numberofclicks=0;
[DllImport(“user32.dll”)]
静态外部无效鼠标事件(int-dwFlags、int-dx、int-dy、int-dwData、int-dwExtraInfo);
私有常量int MOUSEEVENTF_MOVE=0x0001;
private const int MOUSEEVENTF_LEFTDOWN=0x0002;
private const int MOUSEEVENTF_LEFTUP=0x0004;
private const int MOUSEEVENTF_RIGHTDOWN=0x0008;
private const int MOUSEEVENTF_RIGHTUP=0x0010;
私有常量int MOUSEEVENTF_MIDDLEDOWN=0x0020;
私有常量int MOUSEEVENTF_MIDDLEUP=0x0040;
private const int MOUSEEVENTF_ABSOLUTE=0x8000;
私有void StartClicked(对象发送方,事件参数e)
{
点击次数=0;
随机rsn=新随机();
while(点击次数<10)
{
字符串startseconds=textBox1.Text;
int timerstartseconds=Convert.ToInt32(开始秒);
int timertime=rsn.Next(timerstartseconds*1000,((timerstartseconds+3)*1000));
_定时器=新系统.Timers.timer(timertime);
_timer.appeated+=\u timer\u appeated;
_timer.Enabled=true;
textBox2.Clear();
点击次数++;
字符串numbertextbox=numberofclicks.ToString();
textBox2.Text=numbertextbox;
}
}
无效\u计时器\u已过(对象发送器,ElapsedEventArgs e)
{
左键单击();
}
公共静态void LeftClick()
{
鼠标事件(MOUSEEVENTF_LEFTDOWN,Control.MousePosition.X,Control.MousePosition.Y,0,0);
鼠标事件(MOUSEEVENTF_LEFTUP,Control.MousePosition.X,Control.MousePosition.Y,0,0);
}

当你说
\u timer.Enabled=true,其余代码将继续执行。然后,在稍后的某个时间,当计时器滴答作响时,将触发
已用事件

此外,您创建的每个计时器都在滴答作响——它们不会只触发一次

此外,.NET framework中还有许多不同的计时器类。对于像您这样的简单winforms应用程序,我会坚持使用
System.Windows.Forms.Timer
版本。您不必担心线程之类的问题

您可能会得到这样的服务:

private Random rsn = new Random();
private int numberofclicks = 0;
private System.Windows.Forms.Timer _timer;

// set the timer's tick event handler in form_load or similar.
// you could also just drag a timer onto the form and double-click it.

private void StartClicked(object sender, EventArgs e)
{        
    // don't allow starting again until finished
    btnStart.Enabled = false;
    numberofclicks = 0;
    _timer.Interval = /* get randomish interval */
    _timer.Start();
}

void _timer_Tick(object sender, EventArgs e)
{
    _timer.Stop();
    LeftClick();
    numberofclicks++;
    if (numberofclicks >= 10) {
        btnStart.Enabled = true;
    }                      
    else {
        _timer.Interval = /* get randomish interval */
        _timer.Start();
    }
}

问题在于
StartClicked
事件处理程序不阻塞自身。这只是一个简单的方法,在没有任何延迟的情况下,循环10次更改方法级别变量并修改(甚至创建新的!)计时器属性

可以用这种方式(使用简单循环的单个方法)执行您试图执行的操作,但是您必须使用异步事件处理程序,并且不需要计时器。正如前面已经讨论了如何使用经典计时器,我将为您提供这种基于异步的解决方案:

private async void StartClicked(object sender, EventArgs e)
{
    numberofclicks = 0;
    Random rsn = new Random();

    while (numberofclicks < 10)
    {
        string startseconds = textBox1.Text;
        int timerstartseconds = Convert.ToInt32(startseconds);
        int timertime = rsn.Next(timerstartseconds * 1000, ((timerstartseconds + 3) * 1000));

        await Task.Delay(timertime);
        LeftClick();

        textBox2.Clear();
        numberofclicks++;
        string numbertextbox = numberofclicks.ToString();
        textBox2.Text = numbertextbox;
    }
}
private async void StartClicked(对象发送方,事件参数e)
{
点击次数=0;
随机rsn=新随机();
while(点击次数<10)
{
字符串startseconds=textBox1.Text;
int timerstartseconds=Convert.ToInt32(开始秒);
int timertime=rsn.Next(timerstartseconds*1000,((timerstartseconds+3)*1000));
等待任务。延迟(timertime);
左键单击();
textBox2.Clear();
点击次数++;
字符串numbertextbox=numberofclicks.ToString();
textBox2.Text=numbertextbox;
}
}

有关async Wait的更多信息,请阅读。

这很有效!我给了你答案,因为这里的答案比其他选项简单得多(不过,我仍然会投票并尝试他的答案!)如果你不介意的话,异步通常意味着什么?我对编程还比较陌生,我还不完全熟悉这个过程(我没有钱上学,所以我使用了大量的在线课程和YouTube,所以我只是修补了我对其他讲座和搜索的好奇)。@ShoTo是的,这要简单得多。整个async await基础设施的设计目的是简化异步编程(未来、回调、部分并行化…)。它还可以以允许模拟计时器的方式使用。但了解实际计时器、线程关联、同步上下文调用、线程同步构造也非常重要。这是一段值得花费的时间、知识和经验,它将极大地改善你看待和理解更高层次事物的方式。我不知道有什么不同。我最初使用的是Sleep(),但那会锁定UI,我切换到计时器,因为一个教程显示它阻止了锁定,这正是我想要避免的。我将尝试查找一些关于线程及其功能的教程和知识库。再次感谢你!非常感谢你!我得到了我的答案,我也将用这个方法进行实验!所以当我创建一个新的_计时器时,它会选择(比如说3秒)时间,倒计时,触发事件,重置,然后再次倒计时,都是不停的吗?所以我只是创建了10个计时器,每个计时器从不停止并不断点击?