Как я могу добавить индикатор выполнения операции записи криптопотока в C#

Я работал над программой для шифрования и дешифрования файла в рамках проекта. Программа работает нормально сама по себе, но когда я пытаюсь добавить к ней индикатор выполнения, чтобы показать прогресс процесса шифрования / дешифрования, все идет не так. Индикатор выполнения работает довольно хорошо, примерно до 85-90%, а затем выдает ошибку, что значение превысило максимальный предел. Кроме того, панель работает слишком медленно, до появления ошибки возникает около 15-20 секунд, даже когда я шифрую файл размером 16 КБ, что практически не занимает времени, когда выполняется без индикатора выполнения. Я пытался использовать фоновый работник для реализации индикатора выполнения. Может кто-нибудь сказать мне, как я могу заставить индикатор выполнения работать над моей программой?

Вот мой код для процесса шифрования:

public void EncryptFile()
    {

        try
        {
            OpenFileDialog od = new OpenFileDialog();
            od.Title = "Select File To Encrypt";
            od.Filter = "All files (*.*)|*.*";
            string ifile = "";
            if (od.ShowDialog() == DialogResult.OK)
            {
                ifile = od.InitialDirectory + od.FileName;
            }
            else
            {
                MessageBox.Show("No file selected!!");
                goto b;
            }

            if (Path.GetExtension(ifile) == ".arv")
            {
                MessageBox.Show("Error!!File already Encrypted.");
                return;
            }
            string ofile = ifile + ".arv";

        a: string password = Prompt.ShowDialog();
            if (password == "")
            {
                MessageBox.Show("Password Field cannot be blank!!");
                goto a;
            }
            else if (password == null)
            {
                goto b;
            }
            int ph = password.GetHashCode();
            byte[] ia = BitConverter.GetBytes(ph);
            if (BitConverter.IsLittleEndian)
                Array.Reverse(ia);
            byte[] phb = ia;

            UnicodeEncoding UE = new UnicodeEncoding();
            byte[] salt = new byte[] { 10, 20, 30, 40, 50, 60, 70, 80 };
            Rfc2898DeriveBytes k = new Rfc2898DeriveBytes(password, salt);

            string cryptFile = ofile;
            FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);

            AesManaged AMCrypto = new AesManaged();
            AMCrypto.Key = k.GetBytes(32);
            AMCrypto.IV = k.GetBytes(16);

            CryptoStream cs = new CryptoStream(fsCrypt, AMCrypto.CreateEncryptor(), CryptoStreamMode.Write);
            cs.Write(phb, 0, 4);
            FileStream fsIn = new FileStream(ifile, FileMode.Open);

            int data;
            while ((data = fsIn.ReadByte()) != -1)
                cs.WriteByte((byte)data);

            fsIn.Close();
            cs.Close();
            fsCrypt.Close();
            File.Delete(ifile);
            MessageBox.Show("File Encrypted!!");
        b: ;
        }
        catch (Exception e)
        {
            MessageBox.Show(e.ToString());
        }

Подсказка - это отдельный класс, который я создал для создания динамической формы, в которой пользователю предлагается ввести свой пароль. Он выглядит почти как любой запрос на ввод пароля с двумя полями для ввода и проверки пароля и флажком "Показать пароль". Ifile - это входной файл, а ofile - выходной.

Обновление: вот код, который я пробовал с backgroundworker. Кажется, что индикатор выполнения теперь работает, но скорость шифрования значительно снижается, и процесс шифрования завершается до того, как индикатор заполнения заполнен, то есть сообщение "шифрование завершено" отображается до того, как индикатор заполнения заполнен. Также, когда я пытаюсь сделать то же самое для расшифровки, я получаю исключение, говорящее, что криптопоток не поддерживает поиск. Есть идеи?

public Form1()
    {
        InitializeComponent();
        Shown += new EventHandler(Form1_Shown);


        backgroundWorker1.WorkerReportsProgress = true;

        backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);

        backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
    }
    void Form1_Shown(object sender, EventArgs e)
    {

        backgroundWorker1.RunWorkerAsync();
    }
    void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        try
        {

            string ifile = @"F:\abc.mp4";
            int i = 0;
            if (Path.GetExtension(ifile) == ".arv")
            {
                MessageBox.Show("Error!!File already Encrypted.");
                return;
            }
            string ofile = ifile + ".arv";

        a: string password = Prompt.ShowDialog();
            if (password == "")
            {
                MessageBox.Show("Password Field cannot be blank!!");
                goto a;
            }
            else if (password == null)
            {
                goto b;
            }
            int ph = password.GetHashCode();
            byte[] ia = BitConverter.GetBytes(ph);
            if (BitConverter.IsLittleEndian)
                Array.Reverse(ia);
            byte[] phb = ia;

            UnicodeEncoding UE = new UnicodeEncoding();
            byte[] salt = new byte[] { 10, 20, 30, 40, 50, 60, 70, 80 };
            Rfc2898DeriveBytes k = new Rfc2898DeriveBytes(password, salt);

            string cryptFile = ofile;
            FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);

            AesManaged AMCrypto = new AesManaged();
            AMCrypto.Key = k.GetBytes(32);
            AMCrypto.IV = k.GetBytes(16);

            CryptoStream cs = new CryptoStream(fsCrypt, AMCrypto.CreateEncryptor(), CryptoStreamMode.Write);
            cs.Write(phb, 0, 4);
            FileStream fsIn = new FileStream(ifile, FileMode.Open);

            int data;
            double counter = 1;
            while ((data = fsIn.ReadByte()) != -1)
            {
                cs.WriteByte((byte)data);
                backgroundWorker1.ReportProgress((int)((counter / fsIn.Length) * 100));
                counter++;
            }

            fsIn.Close();
            cs.Close();
            fsCrypt.Close();
            File.Delete(ifile);
            MessageBox.Show("File Encrypted!!");
        b: ;
        }
        catch (Exception f)
        {
            MessageBox.Show(f.ToString());
        }

1 ответ

Используя BackgroundWorker:

int data;
double counter = 1;
while ((data = fsIn.ReadByte()) != -1)
{
    cs.WriteByte((byte)data);
    worker.ReportProgress((int)((counter / fs.Length) * 100));
    counter++;
}

Если вы не знаете, как использовать BackgroundWorker:

C# Прогресс бар - не могу обернуть голову вокруг него

Другие вопросы по тегам