Daniel Hamutel
Daniel Hamutel

Reputation: 653

How can i calculate the percentages progress of Process and report to backgroundworker?

What i want to report is the percentages until the convertion of the file is over. How to calculate the percentages and how to report it to the progressBar ?

I added a progressBar1 to the form1 designer.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ConvertVideo
{
    public partial class Form1 : Form
    {
        string InputFile = @"e:\lightningsmov\MVI_7909.MOV";
        string OutputFile = @"e:\lightningsmov\MVI_7909";
        string cmd;
        string exepath = @"E:\myffmpegstatic\ffmpeg-20151217-git-9d1fb9e-win64-static\bin\ffmpeg.exe";

        public Form1()
        {
            InitializeComponent();

            label2.Text = InputFile;
            cmd = " -i \"" + InputFile + "\" \"" + OutputFile + ".mp4" + "\"";
        }

        private void ConvertNow(string cmd)
        {

            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            proc.StartInfo.FileName = exepath;
            proc.StartInfo.Arguments = cmd;
            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.CreateNoWindow = true;
            proc.StartInfo.RedirectStandardOutput = false;
            proc.Start();
            backgroundWorker1.ReportProgress()
            while (proc.HasExited == false)
            {

            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            ConvertNow(cmd);
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {

        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {

        }
    }
}

What i tried so far is this:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;

namespace ConvertVideo
{
    public partial class Form1 : Form
    {
        string InputFile = @"e:\lightningsmov\MVI_7909.MOV";
        string OutputFile = @"e:\lightningsmov\MVI_7909.mp4";
        string cmd;
        string exepath = @"E:\myffmpegstatic\ffmpeg-20151217-git-9d1fb9e-win64-static\bin\ffmpeg.exe";
        FileInfo fi;
        int totalBytes = 0;

        public Form1()
        {
            InitializeComponent();

            fi = new FileInfo(InputFile);
            label2.Text = InputFile;
            cmd = " -i \"" + InputFile + "\" \"" + OutputFile + "\"";
            backgroundWorker1.RunWorkerAsync();
        }

        private void ConvertNow(string cmd)
        {

            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            proc.StartInfo.FileName = exepath;
            proc.StartInfo.Arguments = cmd;
            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.CreateNoWindow = true;
            proc.StartInfo.RedirectStandardOutput = false;
            proc.Start();

            // Gets the size of the file in bytes.
        Int64 iSize = fi.Length;

        int intProgress = 0;
        // Keeps track of the total bytes downloaded so we can update the progress bar.
        Int64 iRunningByteTotal = 0;
            // Open the input file for reading.
        using (FileStream InputFile = new FileStream(OutputFile, FileMode.Open, FileAccess.Read, FileShare.None))
        {
            // Using the FileStream object, we can write the output file.
            using (FileStream OutputFiles = new FileStream(OutputFile, FileMode.Create, FileAccess.Write, FileShare.None))
            {
                // Loop the stream and get the file into the byte buffer.
                int iByteSize = 0;
                byte[] byteBuffer = new byte[iSize];

                while ((iByteSize = InputFile.Read(byteBuffer, 0, byteBuffer.Length)) > 0)                    
                {
                    // Calculate the progress out of a base "100."
                    double dIndex;
                    double dTotal;
                    double dProgressPercentage;
                    // Write the bytes to the file system at the file path specified.                        
                    dIndex = (double)(iRunningByteTotal);
                    dTotal = (double)byteBuffer.Length;
                    dProgressPercentage = (dIndex / dTotal);
                    OutputFiles.Write(byteBuffer, 0, iByteSize);
                    iRunningByteTotal += iByteSize;
                    intProgress = Convert.ToUInt16(dProgressPercentage);
                    // Update the progress bar.
                    backgroundWorker1.ReportProgress((int)(100 * iRunningByteTotal / iSize));

                }                    
                // Close the output file.
                OutputFiles.Close();
            }
            // Close the input file.
            InputFile.Close();
        }


            while (proc.HasExited == false)
            {

            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            ConvertNow(cmd);
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {

        }
    }
}

But getting exception on the line:

using (FileStream OutputFiles = new FileStream(OutputFile, FileMode.Create, FileAccess.Write, FileShare.None))

The exception say the file is in use by another process. I guess it's in use with the Process(proc the ffmpeg).

So i guess i messed it up and using the FileStream is a good idea.

Upvotes: 0

Views: 1011

Answers (1)

Ian
Ian

Reputation: 30813

These lines

// Open the input file for reading.    
using (FileStream InputFile = new FileStream(OutputFile, FileMode.Open, FileAccess.Read, FileShare.None))
{
    // Using the FileStream object, we can write the output file.
    using (FileStream OutputFiles = new FileStream(OutputFile, FileMode.Create, FileAccess.Write, FileShare.None))
    {
        //Your other codes
    }
}

Seem to have the same OutputFile as an input, plus different FileMode and FileAccess. That causes the violation.

You should change your first OutputFile with InputFile then everything would be fine.

Upvotes: 1

Related Questions