C# 正确使用进度条

C# 正确使用进度条,c#,progress-bar,C#,Progress Bar,这是我第一次在C#中使用进度条。 我的代码正在复制一些文件,我希望通过进度条显示进度 我不喜欢我的代码的一点是,我必须遍历所有文件来设置最大的条。。。后来我又通过同样的过程来复制文件 我就是想不出一个办法来保证在酒吧里不做那件事就能顺利进行。我首先要知道最大值,对吗?还是有什么把戏 代码如下所示: 设置最大值: private static void setProgressBar(List<Source> sources, List<Destination> desti

这是我第一次在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;
        }
    
    private static void setProgressBar(列出源,列出目标)
    {
    进度值=0;
    进度。最大值=0;
    foreach(源中的var源)
    {
    progress.max+=System.IO.Directory.GetDirectories(source.Directory,“*”,
    SearchOption.AllDirectories).Count()*目的地.Count+
    System.IO.Directory.GetFiles(source.Directory,“*.*”,SearchOption.AllDirectories.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);
                }
            }
        }
    }
    
    publicstaticvoidcopydata(列表源、列表目的地、RichTextBox、ProgressBar)
    {
    日志=框;
    进度=巴;
    setProgressBar(源、目的地);
    foreach(源中的var源)
    {
    foreach(System.IO.Directory.GetDirectories(source.Directory,“*”)中的var dirPath,
    SearchOption.AllDirectories)
    {
    foreach(目的地中的var目的地)
    {
    记录器(dirPath);
    System.IO.Directory.CreateDirectory(dirPath.Replace(source.Directory,destination.Directory));
    }
    }
    foreach(System.IO.Directory.GetFiles(source.Directory,“***”,SearchOption.AllDirectories)中的var newPath)
    {
    foreach(目的地中的var目的地)
    {
    记录器(新路径);
    Copy(newPath,newPath.Replace(source.directory,destination.directory),true);
    }
    }
    }
    }
    
  • 增加进度条:

    专用静态无效记录器(字符串输出) { log.Text+=“复制:”+output+System.Environment.NewLine; log.SelectionStart=log.Text.Length; log.scrolltocare(); 进度。增量(1); }


所以我运行了两次相同的代码…我不喜欢:)

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

您可以将CopyData方法放在BackgroundWorker中,调用ReportProgress并在ReportProgress事件中设置条形图的新值

下面是一个如何实现的示例。不要调用将从中启动CopyData方法的worker,而要调用static void Main(…)

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;
        }
    }
}
static void Main(字符串[]args)
{
System.ComponentModel.BackgroundWorker worker=新系统.ComponentModel.BackgroundWorker();
worker.ProgressChanged+=worker\u ProgressChanged;
worker.DoWork+=worker\u DoWork;
//工作
worker.RunWorkerAsync();
}
私有静态void Worker_DoWork(对象发送方,System.ComponentModel.DoWorkEventArgs e)
{
//获取价值
var source=null;
var=null;
//CopyData方法
setProgressBar(源、目的地);
foreach(源中的var源)
{
foreach(System.IO.Directory.GetDirectories(source.Directory,“*”,SearchOption.AllDirectories)中的var dirPath)
{
foreach(目的地中的var目的地)
{
记录器(dirPath);
System.IO.Directory.CreateDirectory(dirPath.Replace(source.Directory,destination.Directory));
//增加值1
(发送方为System.ComponentModel.BackgroundWorker)。报告进度(1);
}
}
foreach(System.IO.Directory.GetFiles(source.Directory,“***”,SearchOption.AllDirectories)中的var newPath)
{
foreach(目的地中的var目的地)
{
记录器(新路径);
Copy(newPath,newPath.Replace(source.directory,destination.directory),true);
//增加值1
(发送方为System.ComponentModel.BackgroundWorker)。报告进度(1);
}
}
}
}
私有静态void Worker_ProgressChanged(对象发送方,System.ComponentModel.ProgressChangedEventArgs e)
{
如果(e.ProgressPercentage==1)
{
//若值高于最大值,则会导致异常
if(progress.Value
感谢您的回复,首先缺少一个方法,因此您看不到我在
logger(newPath)
方法中增加了进度条的值。因此它不会从0跳到100。其次,通过BackgroundWorker这样做并不能改善性能最密集的代码(您简化的代码)的情况正在运行两次!假设有2000个目录,该程序将减慢1.5-2次。我正在寻找一种方法来改进它。不知道这是否可能,尽管我读了更多关于后台工作人员的文章,我看到这些目录正在运行