2013-10-13 93 views
0

如果你能想象这是一个加载条:UI元素没有更新

for (int i = 0; i < r.Width/2; i++) //Fills half the loading bar. 
{   
    Rectangle rect = can.Children[3] as Rectangle; //getting the 3rd element of my Canvas 
    if (rect != null) 
    { 
     rect.Fill = brush; 
     rect.Width = i; 
     Thread.Sleep(50); 
    } 
} 

因此,应用程序将不会显示增加额外的矩形的进展。相反,它只是冻结线程休眠的总时间,当for循环结束时它会显示整个线条。

这是为什么?

我知道有一个内置的加载栏,但这只是我遇到的问题的一个例子。

+0

这种情况发生的原因是您在UI线程中运行。 – Jviaches

+0

如果这是在你的UI线程中完成的,thread.sleep会导致你的UI冻结。尝试使用后台工作者。 –

+0

请参阅BackgroundWorker ReportsProgress。在您当前的代码中,直到该循环完成后才会更新UI。 – Paparazzi

回答

2

我建议你开始阅读关于线程,后台工作人员,调度员。除非您向解决方案添加线程,否则整个应用程序将在UI线程的帮助下运行。

如果您有可以连续执行的任务,则无需实现线程或后台工作程序。就你而言,你正在尝试做2个任务。

  1. 更新的矩形,并画出其上的窗口
  2. 睡眠线程50毫秒

当UI线程执行了Thread.Sleep(50);它不能绘制(在矩形中显示进度)。这就是您的应用程序冻结数秒并在您看到任何进度之前完成的原因。我将试着用2个例子来解释这个。

举例:1 添加与IsIndeterminate="True"Button1进度条到您的演示应用程序。

<ProgressBar IsIndeterminate="True" Height="20" Name="progressBar1" Width="177" Visibility="Hidden" /> 

在后面的代码,

private void button1_Click(object sender, RoutedEventArgs e) 
     { 
      progressBar1.Visibility = Visibility.Visible; 
      Thread.Sleep(5000); 
      progressBar1.Visibility = Visibility.Hidden; 
     } 

如果你运行这段代码,你将不会看到任何进度条的代码是越来越串行执行。要确保进度条正常显示并隐藏,请执行以下更改。

例2:

private void button1_Click(object sender, RoutedEventArgs e) 
     { 
      progressBar1.Visibility = Visibility.Visible; 
      Thread t = new Thread(DoMyWork); 
      t.Start(); 
     } 

    private void DoMyWork() 
       { 
        Thread.Sleep(5000); 
        //hide the progress bar after completing your work 
        this.Dispatcher.Invoke((Action)delegate { progressBar1.Visibility = Visibility.Hidden; }); 
       } 

enter image description here

运行这段代码,你可以看到,虽然UI线程更新进度,创造了新的线程执行DoMyWork功能。

您需要this.Dispatcher.Invoke((Action)delegate作为progressBar1在UI线程中创建,并且您不能在另一个线程中访问它。即线程t =新线程(..)

P.S.-这是编码方式的肮脏。这只是给出一个想法,如何在OP的情况下工作。