【问题标题】:Proper use of progress bar正确使用进度条
【发布时间】:2016-08-14 07:16:53
【问题描述】:

这是我第一次在 C# 中使用进度条。 我的代码正在复制一些文件,我想通过进度条显示进度。

我不喜欢我的代码的一点是,我必须通过所有文件来设置栏的最大值……然后我再次通过相同的过程来复制文件。

如果不这样做,我就是想不出一种方法来确保在酒吧中顺利进行。我首先必须知道最大值对吗?还是有什么诀窍?

代码如下:

  • 设置最大值:

    private static void setProgressBar(List<Source> sources, List<Destination> destinations)
    {
        progress.Value = 0;
        progress.Maximum = 0;
    
        foreach (var source in sources)
        {
            progress.Maximum += System.IO.Directory.GetDirectories(source.directory, "*",
                SearchOption.AllDirectories).Count() * destinations.Count +
                System.IO.Directory.GetFiles(source.directory, "*.*", SearchOption.AllDirectories).Count() *
                destinations.Count;
        }
    
  • 复制文件:

    public static void CopyData(List<Source> sources, List<Destination> destinations, RichTextBox box, ProgressBar bar)
    {
        log = box;
        progress = bar;
        setProgressBar(sources, destinations);
    
        foreach (var source in sources)
        {
            foreach (var dirPath in System.IO.Directory.GetDirectories(source.directory, "*",
                SearchOption.AllDirectories))
            {
                foreach (var destination in destinations)
                {
                    logger(dirPath);
                    System.IO.Directory.CreateDirectory(dirPath.Replace(source.directory, destination.directory));
                }
            }
    
            foreach (var newPath in System.IO.Directory.GetFiles(source.directory, "*.*", SearchOption.AllDirectories))
            {
                foreach (var destination in destinations)
                {
                    logger(newPath);
                    File.Copy(newPath, newPath.Replace(source.directory, destination.directory), true);
                }
            }
        }
    }
    
  • 增加进度条:

    私有静态无效记录器(字符串输出) { log.Text += "复制:" + 输出 + System.Environment.NewLine; log.SelectionStart = log.Text.Length; log.ScrollToCaret(); 进度.增量(1); }

所以我两次运行相同的代码......我不喜欢这样:)

【问题讨论】:

    标签: c# progress-bar


    【解决方案1】:

    我在这里看到两个错误:您从未在 CopyData 方法中设置进度条的值 第二个是:您的 CopyData 方法将导致您的 UI 冻结,直到该方法完成(此时进度条将从 0 跳转到 100%)。

    您可以将 CopyData 方法放在 BackgroundWorker 中并调用 ReportProgress 并在 ReportProgress 事件中设置栏的新值。

    这是一个如何完成的示例。而不是static void Main(..) 调用工作人员,您将从那里开始您的 CopyData 方法

    static void Main(string[] args)
    {
        System.ComponentModel.BackgroundWorker worker = new System.ComponentModel.BackgroundWorker();
        worker.ProgressChanged += Worker_ProgressChanged;
        worker.DoWork += Worker_DoWork;
    
        //Do work
        worker.RunWorkerAsync();
    }
    
    private static void Worker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
    {
        //Get Values
        var source = null;
        var destinations = null;
    
        //CopyData Method
        setProgressBar(sources, destinations);
        foreach (var source in sources)
        {
            foreach (var dirPath in System.IO.Directory.GetDirectories(source.directory, "*", SearchOption.AllDirectories))
            {
                foreach (var destination in destinations)
                {
                    logger(dirPath);
                    System.IO.Directory.CreateDirectory(dirPath.Replace(source.directory, destination.directory));
                    //Increase Value by 1
                    (sender as System.ComponentModel.BackgroundWorker).ReportProgress(1);
                }
            }
    
            foreach (var newPath in System.IO.Directory.GetFiles(source.directory, "*.*", SearchOption.AllDirectories))
            {
                foreach (var destination in destinations)
                {
                    logger(newPath);
                    File.Copy(newPath, newPath.Replace(source.directory, destination.directory), true);
                    //Increase Value by 1
                    (sender as System.ComponentModel.BackgroundWorker).ReportProgress(1);
                }
            }
        }
    }
    
    private static void Worker_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
    {
        if (e.ProgressPercentage == 1)
        {
            //If Value gets higher than Maximum it will cause an Exception
            if (progress.Value < progress.Maximum)
                progress.Value += 1;
        }
    }
    
    private static void setProgressBar(List sources, List destinations)
    {
        progress.Value = 0;
        progress.Maximum = 0;
        foreach (var source in sources)
        {
            foreach (var dirPath in System.IO.Directory.GetDirectories(source.directory, "*", SearchOption.AllDirectories))
            {
                //Simplified
                progress.Maximum += destinations.Count;
            }
    
            foreach (var newPath in System.IO.Directory.GetFiles(source.directory, "*.*", SearchOption.AllDirectories))
            {
                //Simplified
                progress.Maximum += destinations.Count;
            }
        }
    }
    

    【讨论】:

    • 感谢您的回复,首先缺少一个方法,因此您看不到我确实在logger(newPath) 方法中增加了进度条的值。所以它不会从 0 跳到 100。其次,通过 BackgroundWorker 执行此操作并不能改善性能最密集的代码(您简化的代码)运行两次的情况!想象一下,有 2000 个目录,程序会减慢 1.5。 - 2次。我正在寻找一种方法来改善它。不知道有没有可能
    • 我又读了几篇关于后台工作人员的文章,发现它们在不同的线程中运行。所以我认为你的回答对我有帮助!
    • 很高兴听到 :) 关于性能密集型代码的另一个问题。您可以忽略直到您写入文件的目录并检查目标文件的目录是否存在。如果没有 -> 创建它。到目前为止,这将是我对这部分问题的唯一想法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-27
    • 1970-01-01
    • 2017-01-16
    • 1970-01-01
    • 1970-01-01
    • 2021-04-15
    相关资源
    最近更新 更多