事件被发送到禁用控件

时间:2010-06-25 01:33:03

标签: c# .net

我有一个问题,我想要一些建议。我的GUI中有一个按钮,它启动了一个复杂的设置序列(连接到模拟到数字转换器,并从回声测深仪开始记录数据)。设置完成后,按钮会从START更改为STOP并具有预期的行为。我所经历的是,在长时间操作期间,如果用户再次点击该按钮(即使它被禁用),一旦重新启用该事件,该事件仍将被发送到该按钮。我发现使其正常工作的唯一方法是在再次启用按钮之前调用Application.DoEvents()。我真正想做的就是吞下发往我按钮的事件,所以DoEvents()看起来有点沉重。由于人们似乎一致反对呼吁DoEvents()我希望这里聪明的头脑可以帮助我提出另一种解决方案。注意我没有尝试过我的演示代码,但它遵循我的真实代码,除了非常长的方法。

  1. 有没有其他方法可以实现这个目标?
  2. 从后台工作者的完成部分调用DoEvents()是否安全(是啊)?

    公共类Form1:表格 {

    BackgroundWorker worker;
    Button startButton;
    bool state;
    
    public Form1() {
        state = false;
        BackgroundWorker worker = new BackgroundWorker();
        worker.DoWork += new DoWorkEventHandler(StartSequence);
        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(ToggleButton);
        startButton = new Button();
        startButton.Text = "START";
        startButton.Click += new System.EventHandler(StartClicked);
        this.Controls.Add(startButton);
    }
    
    private void StartClicked( object sender, EventArgs e ) {
        startButton.Enabled = false;
        worker.RunWorkerAsync( !state );
    }
    
    private void StartSequence( object sender, DoWorkEventArgs e ) {
        bool onState = (bool) e.Argument;
        if ( onState ) {
            RunReallyLongStartupSequence();
        }
        else {
            RunReallyLongStopSequence();
        }
        state = onState;
    }
    
    private void ToggleButton( object sender, RunWorkerCompletedEventArgs e ) {
        startButton.Text = state ? "STOP" : "START";
    
        // THIS IS WHAT I AM WORRIED ABOUT!
        Application.DoEvents();
        startButton.Enabled = true;
    }
    

    }

2 个答案:

答案 0 :(得分:0)

Application.DoEvents()并非严厉,我不认为程序员在所有情况下一致反对DoEventsDoEvents的声誉很差,因为它传统上被用作对编写糟糕代码的神奇黑客修复程序。在您的情况下,这是处理您的情况的正确和正常的方式。

在Windows中,您描述的情况(重新启用按钮时应用了禁用按钮的点击)实际上是控件的正常预期行为。但是,这并不意味着从程序员的角度来看它始终是理想的行为,并且如果您的用户容易在禁用按钮上单击,那么最简单的方法是使用DoEvents,这是只是一种方法告诉表单继续处理它排队的任何事件。自豪地使用它!

答案 1 :(得分:0)

首先,我没有发现DoEvents()一点都不好,特别是当涉及到gui时,你无法想象有多少次它帮助了我,如果你创造了像进度条这样的东西,它如果你想看到它更新是非常强制性的,我只是说我不知道​​为什么它被认为是一个糟糕的命令。 但是关于这个话题,我在这种情况下通常做的事情并不是完全禁用控件 我使用类似于以下内容的东西

public Class myForm :Form
{
    private bool _working = false;

    public myForm()
    {
        _working = true;
        //code here
        this.btnDoStuff.Click += new System.EventHandler(DoStuffClick);

        _working = false;
    }

    private void DoStuffClick(object sender, EventArgs e) 
    {
        if (_working) return;
        _working = true;
        DoStuff();
        _working = false;
    }

    private void DoStuff()
    {
        //your code goes here
    }
}

我发现以上内容对于允许用户一次只做一件事,以及如果我希望能够允许用户做多个事情(例如在执行命令时,能够按下其他按钮)我通常将DoStuff()代码放在另一个线程中执行

如果你在游荡,我使用额外方法(DoStuff())来执行操作的原因是,有时我需要在一个方法中执行其他方法的代码,如果{{1} } flag设置为true,我无法调用_working,因为它不会执行任何操作

我希望我帮助

P.S。是的,我知道已经有两年了,但我前几天才加入了stackoverflow(: