C#,WinForms,等待计时器

时间:2015-03-11 19:38:47

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

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

2 个答案:

答案 0 :(得分: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();
    }
}

答案 1 :(得分:2)

问题在于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