Valetudox
Valetudox

Reputation: 63

backgroundworker+wpf -> frozen window

-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>

Upvotes: 3

Views: 1194

Answers (3)

Henk Holterman
Henk Holterman

Reputation: 273179

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.

Upvotes: 2

Valetudox
Valetudox

Reputation: 63

 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.

Upvotes: 0

Amsakanna
Amsakanna

Reputation: 12934

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.

Upvotes: 0

Related Questions