多线程AES加密RunWorkerCompleted事件永远不会被调用

时间:2016-04-22 22:54:29

标签: c# multithreading encryption

我正在尝试使用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方法:(?

1 个答案:

答案 0 :(得分:1)

由于您未为RijndaelManaged()指定分组密码模式,因此您将获得默认 CBC mode 。在 CBC模式中,加密/解密的每个块都取决于前一个块。这可以防止各个块的加密和解密并行完成。