我有一个问题,我想要一些建议。我的GUI中有一个按钮,它启动了一个复杂的设置序列(连接到模拟到数字转换器,并从回声测深仪开始记录数据)。设置完成后,按钮会从START更改为STOP并具有预期的行为。我所经历的是,在长时间操作期间,如果用户再次点击该按钮(即使它被禁用),一旦重新启用该事件,该事件仍将被发送到该按钮。我发现使其正常工作的唯一方法是在再次启用按钮之前调用Application.DoEvents()。我真正想做的就是吞下发往我按钮的事件,所以DoEvents()看起来有点沉重。由于人们似乎一致反对呼吁DoEvents()我希望这里聪明的头脑可以帮助我提出另一种解决方案。注意我没有尝试过我的演示代码,但它遵循我的真实代码,除了非常长的方法。
从后台工作者的完成部分调用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;
}
}
答案 0 :(得分:0)
Application.DoEvents()
并非严厉,我不认为程序员在所有情况下一致反对DoEvents
。 DoEvents
的声誉很差,因为它传统上被用作对编写糟糕代码的神奇黑客修复程序。在您的情况下,这是处理您的情况的正确和正常的方式。
在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(: