以下是我需要完成的任务列表:
问题在于如何以最高的效率和性能实现这一目标。
我已经尝试使用Parallel.For
封装整个操作块,但我不认为这是解决此问题的最佳方法,因为每个操作都有不同的特征可以解释(如我在上面的列表中指出。
在阅读TPL article中建议的this question之后,在回顾了该问题中的经验数据之后,我认为TPL是我想要的方式。但是我应该如何解决这个问题以获得最大的效率和性能呢?考虑到上传可能是整个操作的瓶颈,我是否应该费心去尝试多线程前两个操作?
感谢您的意见。
编辑:
我已经尝试过使用Tasks和ContinueWith让操作系统处理它,但我想我正在打另一面墙 - 当我等待所有上传任务完成时,看起来垃圾收集器似乎不是清理我上传的数据以便上传,因此我最终耗尽了内存。还有一个必须考虑。
答案 0 :(得分:1)
如果您不能使用.Net 4.5,我建议您使用一个线程从磁盘读取,一个线程用于加密,一个线程用于上传。要在它们之间进行通信,您将在每对线程(1-2和2-3)之间以BlockingCollection<byte[]>
的形式使用生产者 - 消费者模式。
但是既然您可以使用.Net 4.5,那么您可以使用TPL Dataflow,它非常适合此任务。使用TPL数据流意味着您不会浪费线程进行阅读和上传(尽管这很可能对您没什么影响)。更重要的是,这意味着您可以轻松地并行化每个块的加密(假设您可以这样做)。
你要做的是有一个加密块,一个上传块和一个异步任务(实际上,它不一定是一个完整的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();