Search code examples
c#winformsprogress-barfilestream

Sync current progress bar with overall when read a files


So, i try to synchronize two progress bar like that:

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 
}

This works fine, but it's not a synchronization, it - paralleled the progress bar. Can u show me example how to really synchronize two progress bar (current and overall). In my head, I understand that I need to somehow save the read bytes of the current file into a variable, and then add this to the overall progress, but in practice I can’t do it. Second problem is - overall progress bar is start later 1 sec (bcuz wait while loop). P.S. Only filestream, no BGW.


Solution

  • It looks like you have some issues with your counters, it should probably look something like:

    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 );
        }
    }
    

    That should ensure both progress bars are updated continuously. Note that you should probably do the reading on a background thread and use Progress<T>.Report to report progress. Or use asynchronous reads to avoid blocking the UI thread.