如何防止任何按钮单击事件排队,直到第一次调用完成事件句柄 [英] How do I prevent any button click events from queuing until the event handle is finished with the first call

查看:13
本文介绍了如何防止任何按钮单击事件排队,直到第一次调用完成事件句柄的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to prevent a button click from queuing. In testing I have a Form, a Button and in the Code-Behind I have the event handler:

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

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

When I run debug and click the button twice or three or four times rapidly, Debug Output shows each click about five seconds after the last one. What I would like it to show is a single Click and drop the rest until first Event is complete.

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

I have also tried to disable the button, as well as temporarily remove the Handler from the Button_click event. It is all the same results.

推荐答案

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

There are various amounts of trouble you'll get into when you hang-up the UI thread like this. This is certainly one of them, nothing pleasant happens when the user wildly bangs on the button to try to get something noticeable to happen. And sure, those clicks won't get lost, they stay stored in the message queue. To activate your Click event handler again when your event handler stops running.

了解如何使用 BackgroundWorker 或 Task 类来避免此类麻烦非常重要.只需设置按钮的 Enabled 属性即可解决此问题.

Pretty important to learn how to use the BackgroundWorker or Task classes to avoid this kind of trouble. Just setting the button's Enabled property is then enough to solve this problem.

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

Purging the mouse clicks from the message queue is technically possible. But ugly to do, it requires pinvoke. I'll hesitantly post the alternative, don't assume that this is in general a good strategy. You'll need to read this post to have some insight into why DoEvents() is a dangerous method.

    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() 调用将调度所有排队的鼠标点击,因为按钮仍然被禁用,所以它们没有任何反应.IsDisposed 测试对于解决 DoEvents() 的问题至关重要,它确保在代码运行时用户单击窗口的关闭按钮时您的程序不会崩溃.

The Update() call ensures that the user gets the feedback he needs to know that banging the button repeatedly isn't going to do anything useful. The DoEvents() call will dispatch all the queued-up mouse clicks, nothing happens with them since the button is still disabled. The IsDisposed test is essential to solve the problem with DoEvents(), it ensures your program won't crash when the user clicked the window's Close button while the code was running.

使用这篇文章中的 HourGlass 类来提供更多反馈.

Use the HourGlass class in this post to provide more feedback.

这篇关于如何防止任何按钮单击事件排队,直到第一次调用完成事件句柄的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆