基本的C#问题。
我的表单上有两个禁用的文本框,还有一个按钮。按钮目前是这样的:
private void start_Click(object sender, EventArgs e)
{
this.two();
this.hold();
this.one()
}
正如您所看到的那样,它会调用其他三种方法:
我遇到的问题是程序似乎跳过第一次调用两个。只需按住程序一秒钟,然后将一个文本框更改为黑色。
感谢您的帮助!
答案 0 :(得分:3)
正如其他提到的,这是因为您的UI线程在开始刷新显示之前就开始睡眠了。
永远不要在UI线程上调用Thread.Sleep
。它会“阻止”你的程序并激怒你的用户。如果您有一些需要Thread.Sleep
的工作要做,请创建一个新线程,但不要在UI线程中执行。
答案 1 :(得分:3)
您可能遇到的是您在应用程序的主线程上运行此代码,该主线程还负责响应Windows GUI消息(比如在更改文本框颜色后重命名的命令)。在此事件处理程序完全执行之后,程序当前不会处理此消息,此时只有一个文本框是黑色的。
如上所述,Application.DoEvents()将通过中断此处理程序并允许程序在继续之前处理来自GUI的排队消息来解决问题。另一种方法是在BackgroundWorker中运行此代码,后者将使用单独的处理线程告诉GUI线程重新着色文本框,同时不使用Sleep()命令阻止GUI线程。通常,使用多线程方法更好,因为Application.DoEvents()可以通过在当前的事件处理程序尚未完成时强制调用其他事件处理程序而导致意外后果(例如,调用另一个抛出异常的事件处理程序将抛出你已经中断的那个的Application.DoEvents调用,这实际上没有问题。)
答案 2 :(得分:2)
试试这个:
private void start_Click(object sender, EventArgs e)
{
this.two();
Application.DoEvents();
this.hold();
this.one();
}
调用DoEvents();
允许窗口在点击处理程序的中间重新绘制,而不是等到完成。
编辑:请阅读有关此答案的评论......您会发现执行此类阻止操作是“不良做法”。
答案 3 :(得分:2)
它不会跳过对two
的调用,但由于您通过调用Thread.Sleep
阻止了UI线程,因此UI永远无法刷新以显示{的效果{1}}。
你可以这样做:
two
它将在新线程中执行private void start_Click(object sender, EventArgs e)
{
this.two()
Task.Factory.StartNew(() => this.hold())
.ContinueWith(_ => this.one(), TaskScheduler.FromCurrentSynchronizationContext());
}
(因此不会冻结UI),然后,当hold
完成时,它将在UI线程上执行hold
。
答案 4 :(得分:1)
由于您在UI线程上执行Thread.Sleep
,因此您的表单无法更新自身并使用新颜色重新绘制。
您可以在Application.DoEvents
之前引入hold
来电;但是,正如其他人所指出的那样,这会导致你的UI线程在一秒钟内延迟冻结(并且对用户活动没有反应)。
在逻辑中引入延迟的最佳方法是使用Timer
。下面是一些示例代码,在一秒钟的延迟后执行two
。
Timer timer = new Timer { Interval = 1000 };
timer.Tick += (sender, e) =>
{
this.Invoke(new Action(two));
timer.Stop();
timer.Dispose();
};
timer.Start();