.Net 4.5 を使用できない場合は、ディスクからの読み取りに 1 つのスレッド、暗号化に 1 つのスレッド、アップロードに 1 つのスレッドを使用することをお勧めします。BlockingCollection<byte[]>
それらの間で通信するには、スレッドの各ペア (1-2 と 2-3)の間の形式でプロデューサー/コンシューマー パターンを使用します。
しかし、.Net 4.5 を使用できるため、このタスクに最適な TPL Dataflow を使用できます。TPL Dataflow を使用すると、読み取りとアップロードのためにスレッドを浪費することがなくなります (ただし、ほとんど問題にはなりません)。さらに重要なことは、各チャンクの暗号化を簡単に並列化できることです (それができると仮定します)。
暗号化用に 1 つのブロック、アップロード用に 1 つのブロック、ファイルからの読み取り用に 1 つの非同期タスク (実際には、完全である必要はありませんTask
) を用意します。暗号化のブロックは並行して実行するように構成でき、両方のブロックをある程度の最大容量で構成する必要があります (そうしないと、スロットリングが正しく機能せず、ファイル全体が可能な限り高速に読み取られ、OutOfMemoryException が発生する可能性があります)。
コード内:
var uploadBlock = new ActionBlock<byte[]>(
data => uploadStream.WriteAsync(data, 0, data.Length),
new ExecutionDataflowBlockOptions { BoundedCapacity = capacity });
var encryptBlock = new TransformBlock<byte[], byte[]>(
data => Encrypt(data),
new ExecutionDataflowBlockOptions
{
BoundedCapacity = capacity,
MaxDegreeOfParallelism = degreeOfParallelism
});
encryptBlock.LinkTo(
uploadBlock,
new DataflowLinkOptions { PropagateCompletion = true });
while (true)
{
byte[] chunk = new byte[chunkSize];
int read = await fileStream.ReadAsync(chunk, 0, chunk.Length);
if (read == 0)
break;
await encryptBlock.SendAsync(chunk);
}
fileStream.Close();
encryptBlock.Complete();
await uploadBlock.Completion;
uploadStream.Close();