2016-04-21 28 views
0

C#でAESをマルチスレッド化しようとしていますが、この奇妙な例外を修正することはできません。私のバッファサイズはまったく同じですが、それでもサイズが101バイトのファイルの場合はエラーを見ることができるかもしれません。'メモリストリームは展開できません'が、配列のサイズは同じですか?

whileループでは、暗号化されていないバッファを暗号化されたバッファに書き込むelseを作成して(1つのスレッド?)、ifをスキップします。それが同期化された後、私は暗号化されたバッファをrunworkerComplete関数内のファイルに書きたいと思う。暗号化されていないバッファを暗号化されたバッファに書き込もうとすると、問題が発生します。 2番目のバッファのサイズは最初のバッファの長さで作成されていますが、メモリを拡張できないと言われているので、エラーメッセージは私を困惑させます。

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); 
} 

答えて

2

暗号化と復号化は、あなたのoutbufferへのストリームのtoArray(すでにusing文で暗黙の)ストリームをフラッシュし、この問題を解決するために、同じサイズをarn't。

SOLUTION

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); 
     } 
関連する問題