【问题标题】:System.Windows.Forms.ProgressBar with System.Progress across threads does not updateSystem.Windows.Forms.ProgressBar with System.Progress 跨线程不更新
【发布时间】:2022-12-03 01:49:29
【问题描述】:

我试图在 WinForms ProgressBar 上显示解压缩几个文件的进度。

在这里,我创建了一个 System.Progress 和一个更新进度条的处理程序

Progress<int> progress = new Progress<int>(value => {
    progressBar1.Value = value; progressBar1.Update(); }); 

然后我把我的函数交给线程池。

Task t = Task.Run(() => FileUtils.UnzipTo(targetDir,
sourceDir, false, progress));

t.Wait();

在我的解压缩功能中,我对存档中的每个文件执行此操作:

progress.Report(++complete / total * 100);

这肯定是调用的,如果我为我的处理程序使用一个方法,每个文件都会命中断点(尽管我认为为时已晚)

我希望这会更新进度条。

我看到对话框,直到文件完全解压,上面有一个忙碌的光标,但进度没有增加。

我错过了什么?

【问题讨论】:

  • 从另一个线程访问 UI 元素属性字段可能存在问题;尝试将修改 progressBar1 值的代码包装在调度程序中。

标签: c# asynchronous progress-bar threadpool


【解决方案1】:

我相信“你缺少的”是表达式 progress.Report(++complete / total * 100) 中的 integer division。当我复制这个问题时,除非 total 变量被强制转换为浮点变量类型,否则此表达式的计算结果始终为零。

除此之外,我还能够以预期的结果重现您的代码的模拟版本。

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
        buttonUnzip.Click += onButtonUnzip;
    }
    private async void onButtonUnzip(object? sender, EventArgs e)
    {
        progressBar1.Visible = true;
        Progress<int> progress = new Progress<int>(value => {
            progressBar1.Value = value; progressBar1.Update();
        });
        await Task.Run(() => FileUtils.UnzipTo("mockSource", "mockDest", true, progress));
        progressBar1.Visible = false;
    }
}
class FileUtils
{
    static string[] GetFilesMock() => new string[25];
    static void UnzipOneMock(string sourceDir, string targetDir, string file) 
        => Thread.Sleep(TimeSpan.FromMilliseconds(100));
    public static void UnzipTo(
        string sourceDir,
        string targetDir,
        bool option, 
        IProgress<int> progress)
    {
        var files = GetFilesMock();
        int complete = 0;
        int total = files.Length;
        foreach (var file in files)
        {
            UnzipOneMock(sourceDir, targetDir, file);
            progress.Report((int)(++complete / (double)total * 100));
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多