[已解决问题] .NET中非常奇怪的问题.
提问时间: 2008-04-03 19:28
浏览:402 次

private void button1_Click(object sender, EventArgs e)
{
this.button1.Enabled = false;
Form2 f = new Form2();
Thread.Sleep(3000);
f.Show();
this.button1.Enabled = true;
}
以上为一个按钮的事件,当我点击的时候它会不可用,在不可用的时候,我再点击.事实上它也接受了事件,点击几次它会show几个窗口.也就是说即使是在不可能用的状态下它也会接受事件.不知道为什么?

 


提问者:侯垒 - 小虾三级
最佳答案
窗口消息队列...
Windows系统为每个UI线程(这里可以暂时简单理解为窗口)提供了一个(可以这么理解)队列,里边排着所有的输入消息.UI线程会不断地从这个队列里取消息,如果队列是空的,线程就会停下来等到下一个消息到达,如果不为空,就处理获取的消息.

Thread.Sleep只会暂停你自己的线程,却没有暂停系统负责鼠标事件的线程,所以相应的点击消息就排在队列里,等你的线程醒了以后,于是就获取了以前未处理的消息.
2008/4/3 21:03:51 回答者:deerchao
其它回答(3)
首先我不明白你为什么这么用,但是作为一个线程的问题,确是个Good question!

废话少说,先解决问题,你按下边的办法修改一下,肯定只出一个窗口,无论点几下。

private void button1_Click(object sender, EventArgs e)
{
   this.button1.Enabled = false;
   Application.DoEvents();
   Form2 f = new Form2();
   Thread.Sleep(3000);
   Application.DoEvents();
   f.Show();
   this.button1.Enabled = true;
}

这涉及到 缺省的窗口消息处理 和 程序主线程,我想你想一想就会明白的,如果需要进一步讨论,我们再论。
3个月前   回答者:杨连国 - 菜鸟二级
学习了,呵呵
3个月前   回答者:volnet(可以叫我大V) - 小虾三级
虽然还是不知道你的真正目的,给你个办法让你曲线救国:
        private void button1_Click(object sender, EventArgs e)
        {
            if (this.button1.Enabled)
            {
                this.button1.Enabled=false;
                Form2 f = new Form2();
                System.Threading.Thread.Sleep(3000);
                f.Show();
                this.button1.Enabled = true;
            }
        }
3个月前   回答者:风海迷沙 - 小虾三级
评论
3个月前   侯垒 :
那有没有办法,让它只接受一次事件呢!也就是说我点击后,该按钮禁用了.该按钮中的业务执行完成后才可以再用.

3个月前   deerchao :
 关键是不能让主消息循环停下来,不然点击的消息就会等到Button.Enabled为true时才得到处理.
你可以看一下下面的代码:

using System.Windows.Forms;
using System.Threading;
using System;
using Timer=System.Windows.Forms.Timer;

class app
{
static Button btn;
static Form f;
static Timer timer;
static void Main()
{
btn=new Button();
btn.Text="Show new Form";
btn.Click+=ButtonClicked;

timer=new Timer();
//3 seconds
timer.Interval = 3000;
timer.Tick += TimerTick;

f=new Form();
f.Controls.Add(btn);
f.Show();

Application.Run(f);
}

static void ButtonClicked(object sender, EventArgs e)
{
Form f2 = new Form();
f2.Show();
btn.Enabled=false;
timer.Start();
}

static void TimerTick(object sender, EventArgs e)
{
btn.Enabled=true;
timer.Stop();
}
}
3个月前   侯垒 :
我的原来的意思是.在按钮下面有一个业务,而且这个业务执行的时间比较长,所以在用户点击之后,要等一会才可以点击.避免用户的多次点击,因为多次点击它就会执行多次操作.就想到了禁用它来实现,谁知道禁用了它还会接受事件.就是这样一个问题.
3个月前   侯垒 :
加入Thread.Sleep(3000);只是为了在窗口中出现一个延迟,测试的时候在按钮不可用的状态下它也能接收事件.
3个月前   deerchao :
那就用BackgroundWorker执行具体任务,并设置button1.Enabled=true.
button1.Click里只启动这个BackgroundWorker,并把button1.Enabled设置为false.
3个月前   天生俪姿 :
感觉很不错。占个座
2个月前   侯垒 :
@风海迷沙
这个好像也不能解决问题.
   您需要登录以后才能回答!
我的问题    我要提问


快到期问题

> 问题排行榜

有不合适内容,建议去除