You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF中BackgroundWorker无法更新ProgressBar的问题排查

独立窗口ProgressBar不更新问题排查与解决

我需要实现一个独立窗口的ProgressBar,根据另一个窗体的长时处理进度更新。调试时DoWork和ProgressChanged事件都能正常触发,代码也能走到Worker_RunWorkerCompleted并关闭进度条窗口,但ProgressBar的UI完全没有更新。虽然知道WPF推荐用ViewModel,但已经简化代码尝试定位问题,确定是遗漏了某个简单细节,但一直没找到。

相关代码

XAML代码

<Window x:Class="CGXAcquisition.Forms.Dialog.FileProgressBar"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="File Upload Progress" Height="100" Width="300">
    <Grid Margin="20">
        <ProgressBar Minimum="0" Maximum="100" Name="pbStatus" />
        <TextBlock Text="{Binding ElementName=pbStatus, Path=Value, StringFormat={}{0:0}%}" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Grid>
</Window>

进度条窗口后台代码

public partial class FileProgressBar : Window, INotifyPropertyChanged
{
    BackgroundWorker worker = new BackgroundWorker();

    private int fileLines = 0;
    private int totalFileLines = 0;

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string name = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }

    public int FileLines
    {
        get { return fileLines; }
        set 
        { 
            fileLines = value;
            Percentage = (int)Math.Round((double)fileLines / TotalFileLines);
            OnPropertyChanged("FileLines");
        }
    }
    public int TotalFileLines
    {
        get { return totalFileLines; }
        set { totalFileLines = value; }
    }
    public int Percentage { get; set; }

    public FileProgressBar(int totalLines)
    {
        InitializeComponent();
        TotalFileLines = totalLines;
        Loaded += Window_ContentRendered;
    }
    private void Window_ContentRendered(object sender, EventArgs e)
    {
        
        worker.WorkerReportsProgress = true;
        worker.WorkerSupportsCancellation = true;
        worker.DoWork += worker_DoWork;
        worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
        worker.ProgressChanged += worker_ProgressChanged;
        worker.RunWorkerAsync();
    }

    private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        this.Close();
    }

    void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        for(int i = 0; i < 100; i++)
        {
            Thread.Sleep(100);
            int percent = i / 100;
            worker.ReportProgress(percent, i);
        }
    }

    void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        pbStatus.Value = e.ProgressPercentage;
    }

}

调用进度条的代码(另一窗体)

// 构造函数中绑定Loaded事件
Loaded += OnLoaded;

private void OnLoaded(object sender, RoutedEventArgs e)
{
    ShowProgressBar();
}

private void ShowProgressBar()
{
    progress = new FileProgressBar(FileInfo.LineCount);
    progress.Show();
}

问题根源与解决

最终定位到是进度百分比的计算错误:
原代码中DoWork里的计算:

int percent = i / 100;

这里是整数除法,当i取值0到99时,i/100的结果始终为0,导致ReportProgress传递的进度值一直是0,ProgressBar自然没有任何变化。

修正后的规范计算方式:

int percent = (int)((double)i / 100 * 100);

当然也可以直接用i作为进度值(因为循环范围刚好是0-99,对应0%-99%),但如果需要严格按比例计算进度,上述修正后的代码可以正确得到百分比数值。

内容的提问来源于stack exchange,提问作者nutz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 16:55:25