首页 新闻 会员 周边 捐助

winform按钮button变为灰色后依然可以执行 click

0
悬赏园豆:20 [已解决问题] 解决于 2012-08-03 15:14

在winform中的button,点击后先设置enable为false,中间处理其他,最后设置enable为true

但是执行过程中再点击button,依然可以执行click

private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
textBox1.Text += "在执行中········";

//process something


textBox1.Text += "执行完毕!";
button1.Enabled= true;
}

这问题怎么解决

xiaoyaozhe的主页 xiaoyaozhe | 初学一级 | 园豆:123
提问于:2012-08-03 10:23
< >
分享
最佳答案
0

我很关心你的 // process something 到底是什么?

收获园豆:20
Launcher | 高人七级 |园豆:45050 | 2012-08-03 10:24

执行一个函数,调用webservice,是个耗时的操作

xiaoyaozhe | 园豆:123 (初学一级) | 2012-08-03 10:28

@xiaoyaozhe: 也就是说 // process something 是阻塞操作了。你可以见一个简单的WinForm程序,然后添加一个Button,然后在Click中这样写:

button1.Enabled = false;

Thread.Sleep(10000);

button1.Enabled = true;

然后你告诉我,你是不是可以在 10 秒内依然可以点击 button.

Launcher | 园豆:45050 (高人七级) | 2012-08-03 10:46

@程序猿.码农: 单独Sleep我试过,是可以,但是没有解决我这个情况,我也感到很奇怪,我没有用异步,因为耗时操作有好多是改变界面的,当然我可以将ui改变的部分独立出来,不过还没尝试

xiaoyaozhe | 园豆:123 (初学一级) | 2012-08-03 10:53

@xiaoyaozhe: 既然可以,那你就应该找你的代码逻辑的问题。比如 // process something 执行的时间要小于你两次鼠标点击的时间,或者 // process something 执行中更改了button1.Enabled 属性。

Launcher | 园豆:45050 (高人七级) | 2012-08-03 11:15

@程序猿.码农: 你好,首先谢谢你的回答。// process something没有更改enable属性,执行时间绝对大于两次点击间隔,因为第二次点击时候button是灰色的,并且界面是假死的

      我想用 backgroundworker 控件实现,dowork处理远程查询,complete更新ui,但是complete事件一直不触发怎么回事? 

//测试代码 

private void btnSearch_Click(object sender, EventArgs e)

{

btnSearch.Enabled = false;
bgwSearch.RunWorkerAsync();

}

void bgwSearch_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Console.WriteLine("complete");

btnSearch.Enabled = true;
}

void bgwSearch_DoWork(object sender, DoWorkEventArgs e)
{
Console.WriteLine("dowork");
}

xiaoyaozhe | 园豆:123 (初学一级) | 2012-08-03 13:10

@xiaoyaozhe: 如果 // process something 没有更改,那就是别的地方更改了。如果都没有,那只能说明一个问题,你并没有把场景描述清楚,而是根据你自己的臆断认为问题是button在禁用的条件仍能点击。

Launcher | 园豆:45050 (高人七级) | 2012-08-03 13:22

@程序猿.码农: 也就是说,你是怎么判断出button在禁用条件下仍能点击并激发click事件的?

Launcher | 园豆:45050 (高人七级) | 2012-08-03 13:25

@程序猿.码农: 第一次点击,先disable,再执行耗时操作,所以界面是卡的状态,并且button是灰色的,然后再点击button,等一会儿(估计是第一次执行完全以后),第二次的点击就会响应,因为在断点处中断了

xiaoyaozhe | 园豆:123 (初学一级) | 2012-08-03 13:35

@xiaoyaozhe: 我测试过了,的确会有两次click事件,我给你那段代码你告诉我不会,实际也会。

Launcher | 园豆:45050 (高人七级) | 2012-08-03 13:41

@程序猿.码农: 问题出在设置button.Enabled = false; 后,button 并没有被禁用,所以它仍然能响应鼠标点击,只有当该相应事件的函数返回时,它才真正的处于禁用状态。

Launcher | 园豆:45050 (高人七级) | 2012-08-03 13:44

@程序猿.码农: sleep那段代码我测试时候加了句messagebox.show,只中断了一次,去掉以后就中断两次

xiaoyaozhe | 园豆:123 (初学一级) | 2012-08-03 13:53

@程序猿.码农: 这是因为消息机制引起的问题,如果处理click事件的函数执行时间过长,那么下一次点击的消息会存入消息队列,等到当前click处理函数退出以后,再从消息队列获取此消息执行。你可以使用我提供的代码,多次点击button,你会看到多次的重复执行。

解决此问题的办法是尽可能的让click事件处理函数的执行时间缩短,更严谨的做法是自己设置同步事件,忽略无效的点击。

Launcher | 园豆:45050 (高人七级) | 2012-08-03 13:54

@程序猿.码农: backgroundworker的问题我找到了,在winform构造函数里面我执行了如下尝试:

1.button.performclick(),无反应,即button_click未执行

2.将button_click中代码拷贝,即backgroundworker.runasyc(),则complete事件不触发

3.button_click(btnSearch,null),则complete事件不触发

4.什么都不做,则点击button后完全正常,即第一次点击button变灰,再点击不会触发click,直到真正执行完返回

希望帮忙看看怎么回事,谢谢

xiaoyaozhe | 园豆:123 (初学一级) | 2012-08-03 14:07

@xiaoyaozhe:

1, 构造函数里肯定不行,不用尝试了,不仅是click事件,其它例如ComboBox SelectChanged事件也一样。

后面三个问题,我觉得你仍然在错误的描述你的问题,我没法回答你,除非我有你的代码,否则我只能去猜你那里概念理解错了才得出这样的结论。所以,我需要现场,需要用我的知识来还原你的代码逻辑错误。

Launcher | 园豆:45050 (高人七级) | 2012-08-03 14:23

@程序猿.码农: 非常感谢你的回答,这个问题总算告一段落,只要在构造函数里面不操作backgroundworker和button_click,而是直接将dowork的工作执行就没问题,button也可以正常的操纵backgroundworker了。谢谢,诲人不倦啊你,我也该结贴了

xiaoyaozhe | 园豆:123 (初学一级) | 2012-08-03 15:12
其他回答(6)
0

没啥好说的:

把 调用 webservice 改成异步调用

完成后回调 执行

button1.Enabled= true;

八戒的师傅 | 园豆:1472 (小虾三级) | 2012-08-03 10:41

webservice已经是异步的,但对结果的处理和对ui的改变是同步的

情况是这样的,点击以后button变灰,再点击,会等到上次的返回后再执行,就好像有个捕获点击的列表似的

支持(0) 反对(0) xiaoyaozhe | 园豆:123 (初学一级) | 2012-08-03 10:57
0

            button1.Enabled = false;
            Thread.Sleep(10050);
            button1.Enabled = true;

我这样写是不能click的。不过2L貌似说的对

CrazyJinn | 园豆:799 (小虾三级) | 2012-08-03 10:50

谢谢回答,博客园就是好,呵呵

支持(0) 反对(0) xiaoyaozhe | 园豆:123 (初学一级) | 2012-08-03 15:16
0

用多线程吧.子线程完成后让按钮好用.

Tom.汤 | 园豆:3058 (老鸟四级) | 2012-08-03 13:17

backgroundworker其实就是用的多线程,已经解决了

支持(0) 反对(0) xiaoyaozhe | 园豆:123 (初学一级) | 2012-08-03 15:15
0

楼主看你的代码似乎是要防止重复点击的事情,虽然我不知道你的代码具体要干嘛,但是我给你个建议:用一个全局变量,进入click事件时置一个状态,完了后把状态改回去,这样即可。

上面的虽然把问题绕过去了,但是没有全部源码的情况下我只有这个建议-

az235 | 园豆:8483 (大侠五级) | 2012-08-03 14:56

虽然已经解决了,还是谢谢回答啊

支持(0) 反对(0) xiaoyaozhe | 园豆:123 (初学一级) | 2012-08-03 15:14
0

button.Refresh()

kotl | 园豆:5 (初学一级) | 2013-11-19 16:51
0

与楼主遇到同样的关题,主要是很多操作界面上控件的,就算用backgroundwork也会出现问题。

gw2010 | 园豆:1487 (小虾三级) | 2015-02-12 14:00

winform控件的enabled属性更改,只有在点击事件执行完后才会生效,所以我还是用线程处理了

在click中设置enabled,然后new thread,在thread内需要操作UI的地方,执行下面的RunMethod即可

 

private void RunMethod(Action action, Control contol)
  {
   try
   {
    if (InvokeRequired)
    {
     contol.Invoke(action);
    }
    else
    {
     action();
    }
   }
   catch (InvalidOperationException)
   {
    // handleCreated exception
   }
  }

支持(1) 反对(0) xiaoyaozhe | 园豆:123 (初学一级) | 2015-05-26 14:06

@xiaoyaozhe:  是的最后是以Invoke方式处理,确实很麻烦,因为要把操作界面的全部分开。

支持(0) 反对(0) gw2010 | 园豆:1487 (小虾三级) | 2015-05-26 14:15
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册