如何多线程 input/output 进程和 cpu 进程

How to multi-thread input/output process and cpu process

我正在编写一个加密程序来加密文件(大小)来执行此操作,我目前的方法是从文件中读取 1024 个字节,加密这些字节,并将它们写入临时文件,然后重复直到完成。此过程完成后,原始文件将被删除,临时文件将重命名为原始文件的名称。

这是一段处理 n 个字节(n 为 1024)的示例代码:

        private void processChunk(BinaryReader Input, BinaryWriter Output, int n)
    {
        // Read n bytes from the input fileStream
        Byte[] Data = Input.ReadBytes(n);
        // Read n bytes from the streamCipher
        Byte[] cipherData = StreamCipher.OutputBytes(n);
        for (int x = 0; x < n; x++)
            // XOR a byte of the input stream with a corresponding byte of the streamCipher
            Data[x] ^= cipherData[x];
        // Write n bytes to the output fileStream
        Output.Write(Data);
    }

所以我很确定我不能对加密算法进行多线程处理,因为字节是作为密钥流生成的,并且取决于之前生成的字节,但是从文件读取和写入以及 cpu 操作可以吗?

这里最好的策略是什么?

你可以这样做:

  1. 读取所有数据并将其存储在列表中,其中每个条目都是根据 n
  2. 的字节数组
  3. 运行您的加密并将所有加密字节保存在内存中。

  4. 一次写入所有输出字节。

这样你只访问文件两次。

自发地,我会建议 运行 三个线程并行:

  1. 一个 reader 线程将数据块读入内存。
  2. 完成所有工作的加密线程。
  3. 将加密数据写入磁盘的写入器线程。

三个线程通过两个队列进行通信,类似于.Net 4提供的BlockingCollection。参见Fast and Best Producer/consumer queue technique BlockingCollection vs concurrent Queue

因此线程 1 填充队列 1,线程 2 读取队列 1 并填充队列 2,线程 3 读取队列 3。如果任何线程比其他线程快,BlockingCollection 将阻塞读取或写入线程,直到另一边的线程已经赶上了。例如,如果将 BlockingCollection 的最大大小设置为 10,则读取线程将在读取了加密线程之前的 10 个数据块后阻塞。

另一个观察结果:Input.ReadBytes 将为每次读取在堆上分配一个新的字节数组。该数组将在处理当前块后被丢弃,因此如果您有大文件和快速加密算法,内存分配和垃圾收集实际上可能会显着影响性能(.Net 分配时内存缓冲区为零)。相反,您可以使用由读取和加密线程保留和返回的缓冲区池,并使用接受现有缓冲区写入的 Stream.Read 方法。