“内存流不可扩展”,但数组的大小相同

本文关键字:数组 内存 可扩展 | 更新日期: 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);
        }