后台Worker ReportProgress方法不触发ProgressChanged事件

本文关键字:ProgressChanged 事件 Worker ReportProgress 方法 后台 | 更新日期: 2023-09-27 17:49:30

我试图在WPF应用程序中报告进度条的进度,但似乎我的后台工作人员的reportProgress没有触发事件。

下面是我的代码:-

XAML

<Window x:Class="nk_Image_Converter.DynamicControls.ProgressBarWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="ProgressBarWindow" Height="100" Width="500" BorderThickness="0" WindowStyle="None" ResizeMode="NoResize" Background="#d4dce6" Loaded="Window_Loaded" >
<Window.Effect>
    <DropShadowEffect Opacity="0.4"/>
</Window.Effect>
<Border BorderBrush="CadetBlue" BorderThickness="3,0,3,3">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="20"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid Grid.Row="0" Background="CadetBlue"></Grid>
        <Grid Grid.Row="1" Background="Transparent">
            <Label x:Name="Message" Content="Please Wait..." Margin="42,15"/>
            <ProgressBar x:Name="Progressbar" Width="400" Height="25" Margin="47,38,47,14" Foreground="CadetBlue" BorderBrush="CadetBlue" BorderThickness="2"></ProgressBar>
        </Grid>
    </Grid>
</Border>

c#

public partial class ProgressBarWindow : Window
{
    private double _progressCounter = 0;
    private double _progress = 0;
    private BackgroundWorker backgroundWorker = new BackgroundWorker();
    public ProgressBarWindow()
    {
        InitializeComponent();
        this.Left = Application.Current.MainWindow.Left + 250;
        this.Top = Application.Current.MainWindow.Top + 200;
        backgroundWorker.WorkerReportsProgress = true;
        backgroundWorker.ProgressChanged += backgroundWorker_ProgressChanged;
        backgroundWorker.DoWork += backgroundWorker_DoWork;
        backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
        this.Progressbar.Value = 0;
    }
    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        backgroundWorker.RunWorkerAsync();
    }
    private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        this.Dispatcher.Invoke((Action)(() =>
        {
            this._progress = 0;
            addRowstoGrid();
            _progressCounter = (100 / ((MainWindow)Application.Current.MainWindow).fetcher.getNewFiles().Count);
            for (int i = 0; i < ((MainWindow)Application.Current.MainWindow).fetcher.getNewFiles().Count; i++)
            {
                Thread.Sleep(10);
                DynamicControls.ImageButton b = new DynamicControls.ImageButton();
                ((MainWindow)Application.Current.MainWindow)._imageContainer.Height = ((((MainWindow)Application.Current.MainWindow).row + 1) * 125);
                ((MainWindow)Application.Current.MainWindow)._imageContainer.ImageGrid.Height = ((MainWindow)Application.Current.MainWindow)._imageContainer.Height;
                Grid.SetRow(b, ((MainWindow)Application.Current.MainWindow).row);
                Grid.SetColumn(b, ((MainWindow)Application.Current.MainWindow).col++);
                if ((((MainWindow)Application.Current.MainWindow).col + 1) % 5 == 0 && (((MainWindow)Application.Current.MainWindow).col + 1) >= 5)
                {
                    ((MainWindow)Application.Current.MainWindow).col = 0;
                    ++((MainWindow)Application.Current.MainWindow).row;
                }
                ((MainWindow)Application.Current.MainWindow)._imageContainer.ImageGrid.Children.Add(b);
                if (_progressCounter < 99)
                    this._progress += _progressCounter;
                if (_progress > 100)
                    _progress = 100;
                this._progress += ((_progressCounter + _progress) <= 100) ? _progressCounter : 100;

                (sender as BackgroundWorker).ReportProgress((int)this._progress, this._progress);
            }
        }));
    }
    private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
    }
    private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        this.Progressbar.Value = (double)e.UserState;
    }
    public void showDialog()
    {
        ShowDialog();
    }

我还尝试在每个事件方法上添加断点并调试它,但我没有得到任何解决方案

后台Worker ReportProgress方法不触发ProgressChanged事件

问题是,当您调用Dispatcher.Invoke时,代码运行在调度程序线程上,而不是后台线程上。这可能就是它不能报告进度的原因。

你应该:

a)修改你的代码,使它根本不使用后台工作器

b)改变你的后台工作线程,这样它就不会在调度线程上运行代码。

c)如果你需要,你可以改变后台工作线程,让它在调度线程上运行一些片段,但不是全部。你可能只需要在dispatcher线程上运行ui相关的东西;像这样:

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    this._progress = 0;
    addRowstoGrid();
    _progressCounter = (100 / ((MainWindow)Application.Current.MainWindow).fetcher.getNewFiles().Count);
    for (int i = 0; i < ((MainWindow)Application.Current.MainWindow).fetcher.getNewFiles().Count; i++)
    {
        Thread.Sleep(10);
        this.Dispatcher.Invoke((Action)(() =>
        {
            DynamicControls.ImageButton b = new DynamicControls.ImageButton();
            ((MainWindow)Application.Current.MainWindow)._imageContainer.Height = ((((MainWindow)Application.Current.MainWindow).row + 1) * 125);
            ((MainWindow)Application.Current.MainWindow)._imageContainer.ImageGrid.Height = ((MainWindow)Application.Current.MainWindow)._imageContainer.Height;
            Grid.SetRow(b, ((MainWindow)Application.Current.MainWindow).row);
            Grid.SetColumn(b, ((MainWindow)Application.Current.MainWindow).col++);
            if ((((MainWindow)Application.Current.MainWindow).col + 1) % 5 == 0 && (((MainWindow)Application.Current.MainWindow).col + 1) >= 5)
            {
                ((MainWindow)Application.Current.MainWindow).col = 0;
                ++((MainWindow)Application.Current.MainWindow).row;
            }
            ((MainWindow)Application.Current.MainWindow)._imageContainer.ImageGrid.Children.Add(b);
        }));
        if (_progressCounter < 99)
            this._progress += _progressCounter;
        if (_progress > 100)
            _progress = 100;
        this._progress += ((_progressCounter + _progress) <= 100) ? _progressCounter : 100;
        (sender as BackgroundWorker).ReportProgress((int)this._progress, this._progress);
    }
}

我不确定addRowstoGrid做什么,但它可能需要在调度线程上运行。您可以考虑从构造函数而不是从后台线程调用它。重要的部分是在后台线程上调用ReportProgress

另外,需要注意的是,fetcher.getNewFiles()将被调用多次—在循环的每次迭代中调用一次。这是你想要的吗?