winforms 读取文件时,将当前进度条与总体进度条同步

cfh9epnr  于 2023-02-19  发布在  其他
关注(0)|答案(2)|浏览(189)

因此,我尝试同步两个进度条,如:

long TotalSize; //Total size of files in Directory "Source"

foreach (string file in Directory.GetFiles("Source", "*.*", SearchOption.AllDirectories))
{
    long FileSize; //Current file size in recursive search 
    long CurrentFileSize //It's mean `+=` add size of current file in recursive search
    
    using (FileStream readfile = new FileStream(file, FileMode.Open, FileAccess.Read))
    {
        byte[] buffer = new byte[1024 * 1024];
        int Readbyte;
        long TotalByteSize = 0;
        
        while ((readbyte = readfile.Read(buffer, 0, buffer.Length)) > 0)
        {
            TotalByteSize += Readbyte;
            CurrentFileProgress.Value = (int)((float)TotalByteSize / FileSize * 100.0f); //Progress when reading current file bytes
        }
    }
    OverallFilesProgress.Value = (int)((float)CurrentFileSize/ TotalSize * 100.0f); //Overall progress when read all files 
}

这个很好用,但是它不是同步的,它平行于进度条。你能给我演示一下如何真正同步两个进度条吗(当前和总体)。在我的脑海中,我明白我需要以某种方式将当前文件的读取字节保存到一个变量中,然后将此添加到总体进度中,但在实践中我不能这样做。第二个问题是-整体进度条开始晚1秒(bcuz等待而循环)。P.S.只有文件流,没有BGW。

ecfdbz9o

ecfdbz9o1#

看起来您的计数器有一些问题,它可能应该类似于:

int overallTotal = ...; 
int overallCompleted = 0;
foreach(var file in files){
    // open file etc
    int currentCompleted = 0;
    int currentTotal = file.Size;
    while (...){
        overallCompleted += noReadBytes;
        currentCompleted += noReadBytes;
        CurrentFileProgress.Value = (int)(currentCompleted * 100.0f/ currentTotal );
        OverallFilesProgress.Value = (int)(overallCompleted * 100.0f/ overallTotal );
    }
}

这样可以确保两个进度条都能持续更新。注意,您可能应该在后台线程上阅读,并使用Progress<T>.Report报告进度。或者使用异步读取以避免阻塞UI线程。

yduiuuwa

yduiuuwa2#

方法之一是使用for-next循环计数Directory.GetAllFiles()结果,然后使用FileStream.ReadAsync()方法读取(例如)1 MB块,而不会阻塞UI。ProgressBar更新将以这种方式在UI线程上进行,这是它们应该做的。

const int ONE_MB = 0x100000;
private async Task loadFilesAsync(string selectedPath)
{
    string[] files = Directory.GetFiles(selectedPath, "*.*", SearchOption.AllDirectories);

    for (int count = 0; count < files.Length; count++)
    {
        progressBarOverall.Value = (int)((count/(float)files.Length) * 100);
        string path = files[count];

        using (FileStream fileStream = new FileStream(path, FileMode.Open))
        {
            int offset = 0;
            long length = fileStream.Length;
            byte[] buffer = new byte[length];
            int readLength = ONE_MB;
            while (offset != length)
            {
                if (offset + readLength > length)
                {
                    readLength = (int)length - offset;
                }
                offset += await fileStream.ReadAsync(buffer, offset, readLength);
                progressBarSingle.Value = (int)((offset / (float)length) * 100);
            }
        }
    }
    tableLayoutPanelStatus.Visible = false;
}

测试

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
        tsmiBrowseFolder.Click += onClickBrowseFolder;
    }

    private readonly FolderBrowserDialog _folderBrowser = new FolderBrowserDialog
    {
        RootFolder= Environment.SpecialFolder.ApplicationData,
    };
    private void onClickBrowseFolder(object sender, EventArgs e)
    {
        if(_folderBrowser.ShowDialog() == DialogResult.OK) 
        {
            _ = loadFilesAsync(_folderBrowser.SelectedPath);
        }
    }
    .
    .
    .        
}

相关问题