【问题标题】:C#, WinForms, waiting for timersC#,WinForms,等待计时器
【发布时间】:2015-05-13 18:52:57
【问题描述】:

试图了解 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);
    }

【问题讨论】:

    标签: c# while-loop mouseevent system.timers.timer


    【解决方案1】:

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

    您可以以这种方式执行您尝试执行的操作(带有简单循环的单一方法),但是您必须使用异步事件处理程序并且不需要计时器。而another answer 已经讨论了如何使用经典计时器来实现这一点,我将为您提供这样的基于异步的解决方案:

    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;
        }
    }
    

    有关 async-await 的更多信息,您可以阅读MSDN on async-await

    【讨论】:

    • 这行得通!我给了你答案+,因为它在这里比其他选项简单得多(但是,我仍然会投票并尝试他的答案!)如果你不介意,异步一般意味着什么?我对编程还是比较陌生,而且我还不完全熟悉这个过程(我没有钱上学,所以我使用了大量的在线课程和 youtube,所以我只是从其他讲座和搜索中拼凑出我的好奇心) .
    • @ShoTo 是的,它要简单得多。整个异步等待基础架构旨在简化异步编程(期货、回调、部分并行化......)。它也可以以允许模拟计时器的方式使用。但是了解实际的计时器、线程亲和性、同步上下文调用、线程同步结构也非常重要。这是一个值得花时间、知识和经验的时间,这将极大地改善你看待和理解你将遇到的更高级事物的方式。
    • 我不知道有什么不同。我最初使用的是 Sleep(),但它锁定了 UI,我切换到计时器,因为教程显示它阻止了锁定,这是我想要避免的。我将尝试找到一些关于线程及其功能的教程和知识库。再次感谢您!
    【解决方案2】:

    当您说_timer.Enabled = true; 时,您的其余代码将继续执行。然后在一段时间后,当计时器计时,Elapsed 事件被触发。

    此外,您创建的每个计时器都会持续计时 - 它们不仅会触发一次。

    此外,.NET 框架中有许多不同的 Timer 类。对于像您这样的简单 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();
        }
    }
    

    【讨论】:

    • 非常感谢!我得到了答案,我也会尝试这种方法!所以当我创建一个新的_timer时,它会选择(比如说3秒)时间,倒计时,触发事件,重置,然后再次倒计时,都不停?所以我只是创建了 10 个计时器,每个计时器都不会停止并不断点击?
    猜你喜欢
    • 1970-01-01
    • 2012-04-11
    • 1970-01-01
    • 2015-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-17
    • 1970-01-01
    相关资源
    最近更新 更多