win 窗体 按钮 .Enabled:=false 中间做很多事情 还是会触发clik事件思考

本人是delphi ,

btnStart.Enabled:=false;

 之间做一个递归比较耗时,

btnStart.Enabled:=true;

发现在Enabled:=false; 之后还是会触发用户重复clik,诧异了。 百度了一下,发现 C# winform也是有这个问题,同一套机制。百度到下方文章,

避免用户重复点击按钮(使用Enable:=False,消息繁忙时会有堵塞的问题,只能改用Sleep) - findumars - 博客园
https://www.cnblogs.com/findumars/p/6347945.html

// 现象描述:
//    用户点击按钮后程序开始繁忙工作,这时候用户不知道是否成功,就继续点几次
//    采用Enalbe = false ... = true的方式发现还会触发点击,分析原因如下
// 当程序繁忙的时候消息被堵住了
// 所以点击消息还会被处理
// 将队列里的消息处理掉后才打开按钮的Enabled

private void button1_Click(object sender, EventArgs e)
{
    button1.Enabled = false;
    Thread.Sleep(2000);
    richTextBox1.AppendText(Environment.TickCount.ToString() + "/r/n");
    Application.DoEvents(); // 关键语句
    button1.Enabled = true;
}

而我改成: 就可以了。

procedure TForm1.btnStartClick(Sender: TObject);
begin
  btnStart.Enabled:=false;
  ErgodicDirectory('');//递归去做的比较耗时的事情
  Application.ProcessMessages();
  btnStart.Enabled:=true;//在恢复之前 用Application.ProcessMessages();
end;

 

application.ProcessMessages的主要作用使程序在循环时能够相应外界事件。
一般情况下,程序在循环的时候不响应外界事件。直到循环结束为止才能接受和响应外界事件。
application.ProcessMessages可以有效的解决循环循环的独占问题,能够暂时中断应用程序的执行。
比如,你要设计一个计算,这个计算需要循环10000次。当循环开始到500次的时候,用户突然不想计算下去了,它想取消这个计算,
这时候你就可以设置一个cancel按钮,然后在循环体内部合适的位置application.ProcessMessages。来处理cancel按钮的信息,中断循环。
如果你在循环体内没有application.ProcessMessages这句。当循环开始后,程序就被10000次的这个循环独占了,直到循环结束为止。在循环的期间,用户的按什么按钮都没有用。

平时也是常用 application.ProcessMessages 来 防止程序假死。想不到这里也需要用到它。

 

posted @ 2022-06-28 17:48  海蓝7  阅读(283)  评论(0编辑  收藏  举报