2010-04-21 75 views
3

-progressbar始终为0%BackgroundWorker的+ WPF - >冷冻窗口

-the窗口froozen(而DoWork的河)

-if System.threading.thread.sleep(1) - 工作完全

最新问题?

private void btnNext_Click(object sender, RoutedEventArgs e) 
{ 
    this._worker = new BackgroundWorker(); 
    this._worker.DoWork += delegate(object s, DoWorkEventArgs args) 
      { 
       long current = 1; 
       long max = generalMaxSzam(); 


       for (int i = 1; i <= 30; i++) 
       { 
        for (int j = i+1; j <= 30; j++) 
        { 
         for (int c = j+1; c <= 30; c++) 
         { 
          for (int h = c+1; h <= 30; h++) 
          { 
           for (int d = h+1; d <= 30; d++) 
           { 
            int percent = Convert.ToInt32(((decimal)current/(decimal)max) * 100); 
            this._worker.ReportProgress(percent); 
            current++; 
            //System.Threading.Thread.Sleep(1); - it works well 
           } 
          } 
         } 
        } 
       } 
      }; 

      this._worker.WorkerReportsProgress = true; 

this._worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args) 
      { 
       this.Close(); 
      }; 

this._worker.ProgressChanged += delegate(object s, ProgressChangedEventArgs args) 
      {        
       this.statusPG.Value = args.ProgressPercentage;    
      }; 

this._worker.RunWorkerAsync(); 
} 

<Window x:Class="SzerencsejatekProgram.Create" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="Létrehozás" mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Height="500" Width="700">  
    <DockPanel>  
     <Button DockPanel.Dock="Right" Name="btnNext" Width="80" Click="btnNext_Click">Tovább</Button> 
     <StatusBar DockPanel.Dock="Bottom"> 
      <StatusBar.ItemsPanel> 
       <ItemsPanelTemplate> 
        <Grid> 
         <Grid.ColumnDefinitions> 
          <ColumnDefinition Width="*"/> 
          <ColumnDefinition Width="Auto"/> 
          <ColumnDefinition Width="auto"/> 
          <ColumnDefinition Width="auto"/> 
         </Grid.ColumnDefinitions> 
        </Grid> 
       </ItemsPanelTemplate> 
      </StatusBar.ItemsPanel> 
      <StatusBarItem Grid.Column="1"> 
       <TextBlock Name="statusText"></TextBlock> 
      </StatusBarItem> 
      <StatusBarItem Grid.Column="2"> 
       <ProgressBar Name="statusPG" Width="80" Height="18" IsEnabled="False" /> 
      </StatusBarItem> 
      <StatusBarItem Grid.Column="3"> 
       <Button Name="statusB" IsCancel="True" IsEnabled="False">Cancel</Button> 
      </StatusBarItem> 
     </StatusBar> 
    </DockPanel> 
</Window> 

回答

2

您的代码运行非常紧密的循环,并在其中心调用ReportProgress()。

这意味着您的MessageQueue充满了执行Progress更新的请求。

如果您在Bgw线程中构建了一些延迟(Thread.Sleep(100)),您将看到响应性提高。

更实际的解决方案是将报告移出到外部循环。你的情况:

for (int i = 1; i <= 30; i++) 
{ 
    int percent = (i * 100)/30; 
    _worker.ReportProgress(percent); 
    for(int j = 0; ....) 
     .... 
} 

如果你只有1个循环,建立的延迟:“如果((计数器%100)== 0)...`

这里你的目标用户,目标是要求报告进展10到100次。

+0

或者基于%10(00)左右的报告......现在有同事遇到同样的问题,因为他报告了250000条记录的进度。 – cyberzed 2010-04-21 09:37:06

+0

thread.Sleep(100) - >不是解决方案。我认为较少的报告将起作用 – Valetudox 2010-04-21 09:39:35

+0

@cyber,@Value:当然Sleep()不适用于真正的节目。但是这个内部循环只会增加一个var。我已经稍微扩展了我的答案。 – 2010-04-21 10:01:43

0
if (current++ % onePercent == 0) 
        { 
         int percent = Convert.ToInt32(((decimal)current/(decimal)max) * 100); 
         this._worker.ReportProgress(percent, new WorkerUserState { current = current, max = max });       
        } 

这个效果很好。

+0

,因为你减少了频率: ) – Amsakanna 2010-04-21 09:49:03

+0

这是我的解决方案,基于你和Henk Holterman的回答 – Valetudox 2010-04-21 09:54:25

0

ProgressChanged事件的匿名方法将在UI线程上运行。由于您报告的是频繁的进度,因此调度员将排队等待并阻止用户界面。