“内存流不可扩展”,但数组的大小相同
本文关键字:数组 内存 可扩展 | 更新日期: 2024-11-07 14:24:39
我正在尝试在 C# 中多线程 AES,但我似乎无法修复这个奇怪的异常。我的缓冲区大小完全相同,但它仍然说它无法扩展,也许您可以看到错误,这是针对大小为 101 字节的文件。
在 while 循环中,它将跳过 if 并进入 else 创建(一个线程?)将未加密的缓冲区写入加密缓冲区。完成同步后,我想将加密的缓冲区写入 runworkerComplete 函数中的文件。当我尝试将未加密的缓冲区写入加密缓冲区时,问题就出现了。错误消息让我感到困惑,因为第二个缓冲区的大小是用第一个缓冲区的长度创建的,但据说它无法扩展内存!?
static List<BackgroundWorker> threadCompany = new List<BackgroundWorker>();
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, 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);
}
byte[] buffer = new byte[BLOCK_SIZE];
FileInfo fileInfo = new FileInfo(inputFile);
double numBlocks = Math.Ceiling(((double)fileInfo.Length) / BLOCK_SIZE);
int ixCurrentBlock = 0;
while (ixCurrentBlock < numBlocks)
{
//check if any free workers
if (listFreeWorkers.Count > 0)
{
//Get the worker, remove it from the list
BackgroundWorker freeWorker = listFreeWorkers[0];
listFreeWorkers.RemoveAt(0);
//read the next block of the file
int bytes;
if (ixCurrentBlock < numBlocks - 1)
{
bytes = fsIn.Read(buffer, ixCurrentBlock * BLOCK_SIZE, BLOCK_SIZE);
freeWorker.RunWorkerAsync(Tuple.Create(ixCurrentBlock, buffer));
threadCompany.Remove(freeWorker);
}
else //special handling for last block
{
MessageBox.Show((ixCurrentBlock * BLOCK_SIZE) + " " + (int)(fileInfo.Length - ixCurrentBlock * BLOCK_SIZE)); // 0 101
bytes = fsIn.Read(buffer, ixCurrentBlock * BLOCK_SIZE, (int)(fileInfo.Length - ixCurrentBlock * BLOCK_SIZE));
freeWorker.RunWorkerAsync(Tuple.Create(ixCurrentBlock, new byte[(int)(fileInfo.Length - ixCurrentBlock * BLOCK_SIZE)]));
threadCompany.Remove(freeWorker);
}
//now pass it to a worker
//advance to the next block
ixCurrentBlock++;
//update the UI status here
// ...
}
else //no workers free
{
Thread.Sleep(50);
}
}
//if we make it to here we have sent off all the blocks
//now we wait for the threads to complete
bool threadsRunning = false;
while (threadsRunning)
{
threadsRunning = false;
foreach (BackgroundWorker worker in listWorkers)
{
threadsRunning |= worker.IsBusy;
}
//if still running, wait and try again in 50ms
if (threadsRunning)
{
Thread.Sleep(50);
}
}
}
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 = new byte[inBuffer.Length];
//using keyword will automatically close the stream
using (MemoryStream outStream = new MemoryStream(outBuffer)) // issue may be here?
{
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, blockIndex, inBuffer.Length);
}
}
e.Result = Tuple.Create(blockIndex, outBuffer);
}
private static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show(e.Error.Message + " "); // memory is not expendable
Tuple<int, byte[]> t = e.Result as Tuple<int, byte[]>;
int blockIndex = (int)t.Item1;
byte[] buffer = (byte[])t.Item2;
//assumes you have a class variable, _outFile, that is an open filestream
outFile.Write(buffer, blockIndex, buffer.Length);
outFile.Close();
//add the worker back to the free workers list
listFreeWorkers.Add((BackgroundWorker)sender);
}
加密和解密的大小不同 解决此问题 刷新流(已在 using
语句中暗示)以将流阵列到输出缓冲区。
溶液
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;
//using keyword will automatically close the stream
using (MemoryStream outStream = new MemoryStream()) // issue may be here?
{
AesCryptoServiceProvider RMCrypto = new AesCryptoServiceProvider();
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, blockIndex, inBuffer.Length);
}
outBuffer = outStream.ToArray();
}
e.Result = Tuple.Create(blockIndex, outBuffer);
}