zadders
zadders

Reputation: 438

How to sync progress bar with process

I am currently creating a file copying facility that works on console. There are 3 basic classes that exist within this, the first one is the program itself which takes a source and destination and is as follows:

 class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Source:");
            string path = Console.ReadLine();

            Console.WriteLine("target:");

            string target = Console.ReadLine();


            Copy newCopy = new Copy();
            newCopy.CopyFunction(path, target);

            Console.ReadLine();
        }
    }

The second class is the Copy.CS which is as follows:

class Copy

    {
        public void CopyFunction(string source, string destination)
        {
            string sourceFile = source;
            string destinationFile = destination;

            File.Copy(sourceFile, destinationFile);

            Console.Write("Files are being copied... ");
            using (var progress = new ProgressBar())
            {
                for (int i = 0; i <= 100; i++)
                {
                    progress.Report((double)i / 100);
                    Thread.Sleep(20);
                }
            }

            Console.WriteLine("File Copied");         

        }

    }

For the final class, I implemented the ProgressBar.cs class provided by @DanielWolf

https://gist.github.com/DanielSWolf/0ab6a96899cc5377bf54

The problem I'm currently facing is that the file copying function works, and so does the progress bar, but they work separately. For example, the console will spend a while on a blank screen while it processes what's happening, and then after it's completed, a quick animation of the progress bar is displayed.

I was wondering if I could synchronise the progress bar with the copying process so that it moves at a similar rate while it's happening?

Upvotes: 1

Views: 1517

Answers (1)

RobertBaron
RobertBaron

Reputation: 2854

To achieve what you want to do, you need to update the progress bar as you copy the file. One way to do this is simply to copy the file by chunks and report progress as each chunk is copied. I modified your CopyFunction to do just that. Enjoy!

class Copy

{
    public void CopyFunction(string sourcePath, string destinationPath)
    {
        byte[] buffer = new byte[1024 * 10]; // 10K buffer, you can change to larger size.

        using (var progress = new ProgressBar())
        using (FileStream source = new FileStream(sourcePath, FileMode.Open, FileAccess.Read))
        {
            long fileLength = source.Length;
            using (FileStream dest = new FileStream(destinationPath, FileMode.Create, FileAccess.Write))
            {
                long totalBytes = 0;
                int currentBlockSize = 0;

                while ((currentBlockSize = source.Read(buffer, 0, buffer.Length)) > 0)
                {
                    totalBytes += currentBlockSize;
                    dest.Write(buffer, 0, currentBlockSize);
                    progress.Report((double)totalBytes / fileLength);

                }
                progress.Report((double)1.0);
            }

            //File.Copy(sourceFile, destinationFile);

            //Console.Write("Files are being copied... ");
            //using (var progress = new ProgressBar())
            //{
            //    for (int i = 0; i <= 100; i++)
            //    {
            //        progress.Report((double)i / 100);
            //        Thread.Sleep(20);
            //    }
            //}

            Console.WriteLine("File Copied");

        }
    }
}

Upvotes: 3

Related Questions