2010-04-21 62 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線程上運行。由於您報告的是頻繁的進度,因此調度員將排隊等待並阻止用戶界面。