后台工作者+wpf ->冻结的窗口

发布于 2024-08-30 01:29:22 字数 3538 浏览 2 评论 0原文

-进度条始终为 0%

-窗口冻结(DoWork r.)

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

月下伊人醉 2024-09-06 01:29:22

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

这意味着您的 MessageQueue 被执行进度更新的请求淹没。

如果您在 Bgw 线程中构建一些延迟 (Thread.Sleep(100)),您将看到响应能力得到改善。

更实用的解决方案是将报告移至外循环。在您的情况下:

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

如果您只有 1 个循环,请构建延迟:'if ((counter % 100) == 0) ...`

您的目标是用户,目标是对 Reportprogress 进行 10 到 100 次调用。

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.

稚气少女 2024-09-06 01:29:22

ProgressChanged 事件的匿名方法将在 UI 线程上运行。由于您经常报告进度,因此调度程序会将其排队并阻止 UI。

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.

累赘 2024-09-06 01:29:22
 if (current++ % onePercent == 0)
                    {
                         int percent = Convert.ToInt32(((decimal)current / (decimal)max) * 100);
                         this._worker.ReportProgress(percent, new WorkerUserState { current = current, max = max });                        
                    }

这很好用。

 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文