views:

165

answers:

3

-progressbar always 0%

-the window is froozen (while DoWork r.)

-if System.threading.thread.sleep(1) on - works perfectly

whats the problem?

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>
+1  A: 

Your code runs a very tight loop and at its center it calls ReportProgress().

This means that your MessageQueue is swamped with requests to execute the Progress updates.

If you build some delay (Thread.Sleep(100)) into the Bgw thread you will see the responsiveness improve.

A more practical solution is to move the reporting out to the outer loop. In your case:

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

If you only have 1 loop, build in a delay: 'if ((counter % 100) == 0) ...`

Your target here is the user, aim for between 10 and 100 calls to Reportprogress.

Henk Holterman
Or report based on %10(00) or so...have a coworker with the same problem at the moment cause he's reporting progress on 250000 records.
cyberzed
thread.Sleep(100) -> not a solution. i think less report will work
Valetudox
@cyber, @Value: of course Sleep() is not for real programs. But this inner loop only increments a var. I have extended my answer a little.
Henk Holterman
Hmm well it is 30^5 times it get's progressupdates so I would still prefer reporting less progress. Often goal of progressupdates is to show the user that the system ain't dead, since they don't really care if you have 10 or 10.000.000 million records (unless you deliberately tell them how many items you'll progress.
cyberzed
@cyberzed, I think I addressed bot those problems in my last revision...
Henk Holterman
Ah, didn't see that you were in the "i" loop and not the "d" loop :D
cyberzed
A: 
 if (current++ % onePercent == 0)
                    {
                         int percent = Convert.ToInt32(((decimal)current / (decimal)max) * 100);
                         this._worker.ReportProgress(percent, new WorkerUserState { current = current, max = max });                        
                    }

this works well.

Valetudox
since you've reduced the frequency:)
Veer
this is my solution based on your and Henk Holterman answer
Valetudox
A: 

Your anonymous method for the ProgressChanged event will run on UI thread. since you're reporting frequent progress it will be queued up in by the dispatcher and blocks the UI.

Veer