private void button1_Click(object sender, RoutedEventArgs e)
{
int i = 0;
while (i < 500)
{
label1.Content = i.ToString();
// System.Threading.Thread.Sleep(2000);
++i;
}
}
每次变量递增时,我都会尝试更新Label的内容,但是只有在while循环终止后,label1的内容才会更改一次。我认为计数器变量的增量是如此之快以至于UI线程无法赶上它,所以我想让线程空闲2秒,希望看到label1更改值500次。它也没用。为什么呢?
答案 0 :(得分:7)
正如其他人所说,问题在于你正在阻止UI线程。
我建议您使用DispatcherTimer
来安排更新,而不是将建议与Application.DoEvents
一起使用。示例代码:
DispatcherTimer timer = new DispatcherTimer();
timer.Tick += delegate
{
label.Content = counter.ToString();
counter++;
if (counter == 500)
{
timer.Stop();
}
};
timer.Interval = TimeSpan.FromMilliseconds(2000);
timer.Start();
(我不确定Application.DoEvents
是否可以在WPF中运行,而且它通常被认为是不好的做法。如果它 工作,我怀疑它是否可以保证在将来有效为了这个原因,在同一个应用程序中混合使用两个UI听起来对我来说真是个坏主意。)
你可以使用Timer
(System.Threading.Timer
或System.Timers.Timer
),但在这两种情况下,你都需要编组回调度程序线程。 DispatcherTimer
使这更简单 - Tick
事件总是在Dispatcher
线程中触发。
编辑:如果确实想要等同于DoEvents
,那么我验证的代码确实有用,并且基于MSDN docs for Dispatcher.PushFrame
解释如何执行相当于Application.DoEvents
但来自WPF:
public void DoEvents()
{
DispatcherFrame frame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
new DispatcherOperationCallback(ExitFrames), frame);
Dispatcher.PushFrame(frame);
}
public object ExitFrames(object f)
{
((DispatcherFrame)f).Continue = false;
return null;
}
private void ButtonClick(object sender, RoutedEventArgs e)
{
for (int i = 0; i < 500; i++)
{
label.Content = i.ToString();
DoEvents();
}
}
我仍然不建议这样做 - WPF(如Windows Forms)是基于事件驱动的工作方式设计的。
答案 1 :(得分:0)
处理程序正在占用事件循环。
一种选择是使用Application.DoEvents方法来允许执行绘制操作。 请注意,这被认为是不好的做法,因为Thread.Sleep将使UI无响应。
private void button1_Click(object sender, RoutedEventArgs e)
{
int i = 0;
while (i < 500)
{
label1.Content = i.ToString();
System.Threading.Thread.Sleep(2000);
Application.DoEvents();
++i;
}
}
另一个选择是对每个label1.Content
= ..操作使用Control.BeginInvoke。
答案 2 :(得分:0)
像这样更新你的方法:
private void button1_Click(object sender, RoutedEventArgs e)
{
int i = 0;
while (i < 500)
{
label1.Content = i.ToString();
//Update the UI
Application.DoEvents();
// System.Threading.Thread.Sleep(2000);
++i;
}
}
这是最简单的方法。但不是首选的。首选的是使用backgroundworker
来满足这种需求。
答案 3 :(得分:0)
“如果我们处理按钮的click事件处理程序内部的整个搜索,我们永远不会给UI线程处理其他事件的机会.UI将无法响应输入或处理消息。它永远不会重新粉刷,永远不会回应按钮点击。“ - Source。
无论如何,你要做的是创建一个执行for循环的工作线程,并使用Dispatcher.BeginInvoke更新UI。
答案 4 :(得分:-1)
我认为你需要的是
Label.Update();