Как я могу добавить индикатор выполнения операции записи криптопотока в 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
: