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