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

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

问题描述

我想阻止按钮点击排队。在测试中,我有一个表单,一个按钮和代码背后我有事件处理程序:

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.

推荐答案

在挂断界面时会遇到各种麻烦这样的线程这当然是其中之一,当用户猛烈地敲击按钮以尝试获得某些可以发生的事情时,没有任何愉悦的发生。而且确保这些点击不会丢失,它们会保存在消息队列中。当您的事件处理程序停止运行时,再次激活您的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天全站免登陆