首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >具有可变边界的多个依赖操作并行化

具有可变边界的多个依赖操作并行化
EN

Stack Overflow用户
提问于 2012-12-19 23:48:47
回答 1查看 121关注 0票数 4

下面是我需要完成的任务列表:

  1. 读取文件块(磁盘IO绑定)
  2. 加密所述块(CPU绑定)
  3. 上传所述块(网络IO绑定)
  4. 重复,直到上传文件

问题在于如何以最大的效率和性能完成这一任务。

我尝试过使用Parallel.For封装整个操作块,但考虑到每个操作都有可以考虑的不同特性(正如我在上面的列表中指出的那样),我认为这不是解决这个问题的最佳方法。

在阅读了TPL条款这个问题中的建议之后,在回顾了这个问题中的经验数据之后,我认为TPL是我想要的方式。但是,为了最大限度地提高效率和性能,我应该如何打破这种局面呢?考虑到上传很可能是整个操作的瓶颈,我是否应该费心去尝试多线程前两个操作呢?

谢谢你的意见。

编辑:

我试着用任务和ContinueWith来让操作系统来处理它,但我想我碰到了另一堵墙--当我等待所有上传任务完成时,垃圾收集器似乎没有清理我读到的上传数据,因此我最终耗尽了内存。又一个必须考虑的问题。

EN

回答 1

Stack Overflow用户

发布于 2012-12-22 14:09:18

如果您不能使用.Net 4.5,我建议您使用一个线程从磁盘读取,一个线程用于加密,一个线程用于上传。要在它们之间进行通信,您可以在每一对线程(1-2和2-3)之间使用生产者-使用者模式( BlockingCollection<byte[]> )。

但是,由于您可以使用.Net 4.5,所以可以使用,这非常适合这个任务。使用that意味着您不会浪费线程来阅读和上传(尽管这对您来说不太重要)。更重要的是,这意味着您可以轻松地并行化每个块的加密(假设您可以这样做)。

您要做的是有一个块用于加密,一个块用于上传,一个异步任务(实际上,它不必是一个完整的Task)来读取文件。用于加密的块可以配置为并行执行,这两个块都应该配置一些最大容量(否则,节流将不能正常工作,整个文件将被尽可能快地读取,这可能导致OutOfMemoryException)。

代码:

代码语言:javascript
运行
复制
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();
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13963134

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档