代码之家  ›  专栏  ›  技术社区  ›  Steve Hiner

处理WinForms应用程序中用户双击按钮的最佳方法?

  •  4
  • Steve Hiner  · 技术社区  · 16 年前

    我正在开发一个WinForms应用程序,其中有一个用户控件。用户控件中的按钮将事件提升到要由其他代码处理的窗体。其中一个按钮启动一些进程,如果它们同时运行,将导致问题。我在代码中有管理状态的逻辑,所以通常用户不能运行已经运行的进程。但是,如果用户双击该按钮,它将以如此快的速度启动该过程两次,我很难阻止它。

    我想知道,最好的办法是什么?

    我开始是在单击事件中禁用按钮,但第二次单击是在第一次单击导致按钮被禁用之前出现的。在代码中设置其他标志也没有捕捉到它。

    我正在考虑在引发事件的代码上添加某种同步锁,但我想知道你们中是否有人有更好的想法。

    由于这个项目基本上是完整的,我正在寻找不涉及应用程序彻底重写的答案(比如实现复合应用程序块),但是,也可以随意发布这些想法,因为我可以在我的下一个项目中使用它们。

    8 回复  |  直到 15 年前
        1
  •  5
  •   HanClinto    16 年前

    确保禁用按钮或执行的任何其他锁定是在事件处理程序中执行的/first/操作。如果你能在第一条指令触发之前将两个点击事件排队,我会非常惊讶,但是如果你在一台速度非常慢的计算机上,而这台计算机被其他应用程序困住了,我想这是可能的。

    在这种情况下,请使用标志。

    private bool runningExclusiveProcess = false;
    
    public void onClickHandler(object sender, EventArgs e)
    {
        if (!runningExclusiveProcess)
        {
            runningExclusiveProcess = true;
            myButton.Enabled = false;
    
            // Do super secret stuff here
    
            // If your task is synchronous, then undo your flag here:
            runningExclusiveProcess = false;
            myButton.Enabled = true;
        }
    }
    
    // Otherwise, if your task is asynchronous with a callback, then undo your flag here:
    public void taskCompletedCallback()
    {
        runningExclusiveProcess = false;
        myButton.Enabled = true;
    }
    

    如果你仍然可以点击两下这样的东西,那么确保你不是意外订阅了一个双击事件,或者其他任何不稳定的事情正在发生。

        2
  •  3
  •   Jason Jackson    16 年前

    你处理这件事两次了吗?

    我是 非常 令人惊讶的是,第二次点击是在你可以禁用按钮之前。我会确保你不会两次参加这个活动。我以前是偶然做的。然后你会得到两个事件,几乎是瞬间的。

        3
  •  1
  •   Nick    16 年前

    在按钮事件处理程序完成之前,不会设置该按钮上的禁用标志,并且任何其他单击都将在第一次单击之后的Windows消息队列中排队。确保按钮事件处理程序快速完成以释放UI线程。有几种方法可以做到这一点,但都涉及到EATHER生成一个线程或保持一个工作线程就绪并等待一个autoreseteevent。

        4
  •  0
  •   Michael Zuschlag    16 年前

    你有没有在按钮上贴上图标?无论如何,使用代码来防止同时运行两个进程,但是如果您的按钮看起来和行为类似于常规的命令按钮(矩形,仅文本标签,“凸起”的表面,单击时会降低),则可以减少在人的一侧双击。只是一个想法。

        5
  •  0
  •   Erick    16 年前

    单击按钮后立即禁用。因此,事件不能处理两次。一旦事件处理完毕,您就可以重新启用该按钮。

        6
  •  0
  •   nbdeveloper    15 年前

    如果充其量只是些轶事,那么经过核对的答案就很接近了。对于没有意识的人来说,它缺少太多的代码而没有意义。我写了一篇关于使用计时器和线程的文章,代码示例非常容易理解。尝试阅读它,并通过在新线程中运行任务进程来查看是否可以从上面的示例中设置标志:

    http://www.robault.com/category/Threading.aspx

        7
  •  -1
  •   Piskvor left the building Rohit Kumar    16 年前

    在用户第一次单击按钮之后和开始任务之前禁用该按钮。任务完成后,重新启用按钮。

        8
  •  -3
  •   mjwills Myles McDonnell    16 年前

    我先把按钮关掉了 在Click事件中,但在第二个事件中 单击在第一次单击之前进入 使按钮被禁用。 在代码中设置其他标志没有 抓住它。

    如果WinForms本身是单线程的,那么在第一个线程的处理完成之前,第二次单击就不可能触发(除非您使用新线程或BackgroundWorkers等)。

    你能给我们看一个例子说明你的问题吗?