如何防止任何按钮单击事件排队,直到事件句柄完成第一次调用

本文关键字:事件 句柄 调用 第一次 任何 何防止 按钮 单击 排队 | 更新日期: 2023-09-27 17:56:41

我想防止按钮点击排队。在测试中,我有一个窗体,一个按钮,在代码隐藏中,我有一个事件处理程序:

    private void button1_Click(object sender, EventArgs e)
    {
        if (_codeRunning)
            return;
        _codeRunning = true;
        //Application.DoEvents();
        //button1.Enabled = false;
        _click ++;
        Debug.WriteLine("Click Number: " + _click);
        Task.Delay(5000).Wait();
        //button1.Enabled = true;
        _codeRunning = false;
    }

当我运行调试并快速单击按钮两次或三次或四次时,调试输出显示每次单击后大约五秒。我希望它显示的是单击并删除其余部分,直到第一个事件完成。

我还尝试禁用该按钮,并从Button_click事件中暂时删除处理程序。结果都是一样的。

如何防止任何按钮单击事件排队,直到事件句柄完成第一次调用

当您像这样挂断 UI 线程时,会遇到各种麻烦。 这当然是其中之一,当用户疯狂地敲击按钮以试图让一些明显的事情发生时,不会发生任何愉快的事情。 当然,这些点击不会丢失,它们会存储在消息队列中。 在事件处理程序停止运行时再次激活 Click 事件处理程序。

学习如何使用BackgroundWorker 或 Task 类来避免这种麻烦非常重要。 只需设置按钮的 Enabled 属性就足以解决此问题。

从消息队列中清除鼠标单击在技术上是可行的。 但难看的是,它需要平唤。 我会犹豫地发布替代方案,不要认为这通常是一个很好的策略。 你需要阅读这篇文章,以了解为什么DoEvents()是一种危险的方法。

    private void button1_Click(object sender, EventArgs e) {
        button1.Enabled = false;
        button1.Update();
        '' long running code
        ''...
        Application.DoEvents();
        if (!button1.IsDisposed) button1.Enabled = true;
    }

Update() 调用确保用户获得他需要的反馈,知道反复敲击按钮不会做任何有用的事情。 DoEvents() 调用将调度所有排队的鼠标单击,由于按钮仍处于禁用状态,因此它们不会发生任何反应。 IsDispose测试对于解决DoEvents()的问题至关重要,它确保当用户在代码运行时单击窗口的"关闭"按钮时,程序不会崩溃。

使用本文中的 HourGlass 类来提供更多反馈。

我有一个按钮,点击事件将运行一个方法。同样的问题发生了,当用户多次单击该方法时,该方法被多次触发。所以我做了一个布尔值,并在方法开始时更改了它的值。

private bool IsTaskRunning = false;
private void MyMethod()
{
    if ( IsTaskRunning==false )
    {
        IsTaskRunning=true;
        // My heavy duty code that takes a long time
        IsTaskRunning=false; // When method is finished
    }
}

因此,现在该方法仅在上次完成时才运行。