我正在尝试使用Backgroundworker实现多线程AES加密以完成事件。首先,我读取缓冲区将其发送到doworker事件。在线程完成后,它会将onbuffer写入加密的outbuffer,它需要在RunWorkerCompleted方法中写入,但它永远不会被调用。
然而,当我使用消息框慢慢调试时,该功能会启动!成功地给了我加密文件。我不明白,如果有人可以帮助我如何将其转换为线程池,我将不胜感激?或者解释为什么它在完成后不会调用runworkercomplete,因为它在doworker事件中显示了messagebox但在runworkercomplete事件中没有显示?
static List<BackgroundWorker> listWorkers = new List<BackgroundWorker>();
static List<BackgroundWorker> listFreeWorkers = new List<BackgroundWorker>();
static FileStream fsIn;
static string file;
static byte[] key;
const int BLOCK_SIZE = 1000;
static FileStream outFile;
public static void EncryptFile(string inputFile, string outputFile, string sKey, String privateKey, ProgressBar progress)
{
String fileName = inputFile;
fileName = "\\" + fileName.Split('\\').Last();
var progres = new Progress<int>(value => progress.Value = value);
file = outputFile + fileName;
fsIn = new FileStream(inputFile, FileMode.Open);
outFile = new FileStream(file, FileMode.Create);
key = new UnicodeEncoding().GetBytes(sKey);
for (int t = 0; t < 4; t++)
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
listWorkers.Add(worker);
listFreeWorkers.Add(worker);
}
FileInfo fileInfo = new FileInfo(inputFile);
double numBlocks = Math.Ceiling(((double)fileInfo.Length) / BLOCK_SIZE);
int ixCurrentBlock = 0;
while (ixCurrentBlock < numBlocks)
{
if (listFreeWorkers.Count > 0)
{
BackgroundWorker freeWorker = listFreeWorkers[0];
listFreeWorkers.Remove(freeWorker);
int bytes;
if (ixCurrentBlock < numBlocks - 1)
{
byte[] buffer = new byte[BLOCK_SIZE];
bytes = fsIn.Read(buffer, 0, BLOCK_SIZE);
freeWorker.RunWorkerAsync(Tuple.Create(ixCurrentBlock * BLOCK_SIZE, buffer));
}
else //special handling for last block
{
int size = (int)(fileInfo.Length - ixCurrentBlock * BLOCK_SIZE);
byte[] buffer = new byte[size];
bytes = fsIn.Read(buffer, 0, size);
freeWorker.RunWorkerAsync(Tuple.Create(0, buffer));
}
ixCurrentBlock++;
}
else
{
}
}
var hasAllThreadsFinished1 = (from worker in listWorkers
where worker.IsBusy
select worker).ToList().Count;
while (hasAllThreadsFinished1 != 0)
{
hasAllThreadsFinished1 = (from worker in listWorkers
where worker.IsBusy
select worker).ToList().Count;
}
fsIn.Close();
outFile.Close();
byte[] hash = Hashing.HashFile(outputFile + fileName, privateKey);
File.WriteAllBytes(outputFile + "\\Hashing.txt", hash);
}
private static void worker_DoWork(object sender, DoWorkEventArgs e)
{
Tuple<int, byte[]> t = e.Argument as Tuple<int, byte[]>;
//int blockIndex = (int)t.Item1;
byte[] inBuffer = (byte[])t.Item2;
byte[] outBuffer;
MessageBox.Show("Started");
using (MemoryStream outStream = new MemoryStream())
{
RijndaelManaged RMCrypto = new RijndaelManaged();
using (CryptoStream cs = new CryptoStream(outStream,
RMCrypto.CreateEncryptor(key, key),
CryptoStreamMode.Write))
{
// I want to write inbuffer non encrypted to outbuffer encrypted.
cs.Write(inBuffer, 0, inBuffer.Length);
}
outBuffer = outStream.ToArray();
}
e.Result = Tuple.Create(0, outBuffer);
MessageBox.Show("done function");
}
static Object pen = new Object();
private static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Done");
Tuple<int, byte[]> t = e.Result as Tuple<int, byte[]>;
//int blockIndex = (int)t.Item1;
byte[] buffer = (byte[])t.Item2;
bool b = true;
while (b)
{
lock (pen)
{
outFile.Write(buffer, 0, buffer.Length);
listFreeWorkers.Add((BackgroundWorker)sender);
MessageBox.Show("Done");
b = false;
}
}
}
更新
错误往往是4个线程同时运行时。他们只是卡住我在这里使用messageBox进行测试。
using (CryptoStream cs = new CryptoStream(outStream,
RMCrypto.CreateEncryptor(key, key),
CryptoStreamMode.Write))
{
// I want to write inbuffer non encrypted to outbuffer encrypted.
cs.Write(inBuffer, 0, inBuffer.Length);
}
outBuffer = outStream.ToArray();
MessageBox.Show(outBuffer[0] + " done function");
会给我加密文件。这没有任何意义,为什么我的线程不能同时运行dowork方法:(?
答案 0 :(得分:1)
由于您未为RijndaelManaged()
指定分组密码模式,因此您将获得默认 CBC mode 。在 CBC模式中,加密/解密的每个块都取决于前一个块。这可以防止各个块的加密和解密并行完成。