我正在编写一个C#类库,使用IStream通过COM自动化传输大量数据。它使用CreateStreamOnHGlobal API调用来创建流,并使用System.Runtime.InteropServices.COMTypes.IStream中的方法来处理它。
我的问题是,在传输大量数据时,控制内存占用的最佳方法是什么?将100MB以上的文件数据加载到内存中似乎很浪费,客户端应用程序需要等到该过程完成后再下载任何内容。
我的计划是创建一个合理大小的流并多次写入。在编写下一个数据块之前,请回到开头并从头开始覆盖。我是否采用正确的方法,是否有更好的方法来解决这个问题?
答案 0 :(得分:1)
你能看看微软关于大数据和流媒体的这篇文章吗?在我的一个项目中,我们将相同的流一直传递给客户端,因为我们从不进行缓冲并将其作为流进行维护,直到客户端获取它(通过Web的响应流)或文件流为止。在Windows应用程序中,我们能够在服务器上留下非常少的内存占用量。
尝试查看WCF和TransferMode = Streamed与MTOM编码相结合是否有助于满足您的要求。
大数据和流媒体=> http://msdn.microsoft.com/en-us/library/ms733742.aspx
答案 1 :(得分:1)
考虑使用使用属性FILE_ATTRIBUTE_TEMPORARY和FILE_FLAG_DELETE_ON_CLOSE创建的文件。把东西写在那里。除非内存耗尽,Windows将尝试将其保留在磁盘缓存中。当你关闭手柄或程序终止(或崩溃!)时它会自毁。我了解了它here。
答案 2 :(得分:0)
对于大量数据的临时本地存储,内存映射文件通常是个好主意。它将内存管理职责交给Windows,后者最了解如何操作。如果您没有指定文件,它将映射到页面文件,除非有必要,否则永远不会进入物理磁盘。
如果您使用的是.NET 4.0,则会有managed API个内存映射文件。
答案 3 :(得分:0)
每个流实现在缓冲区上。大多数情况下,您将100%控制缓冲区大小。您可以调整缓冲区大小以调整性能与内存使用平衡。如果你没有在同一时间打开数百个流,我建议尽可能大的流量:
var readStream = new System.IO.File.OpenRead(sourceFilePath); var writeStream = new System.Io.File.Create(destinationFile);
byte [] buffer = new bytes [ bufferSize ]; int readLength; 而((读数长度= readStream.Read(0,0,的 BUFFERSIZE 强>))大于0) {
writeStream.Write(缓冲液,0,读数长度); }writeStream.Close(); readStream.Close();
答案 4 :(得分:0)
使用Windows Communication Foundation(WCF)发送大型邮件时,通常需要限制用于缓冲这些邮件的内存量。一种可能的解决方案是流式传输消息体(假设大部分数据在体内)。但是,某些协议需要缓冲整个消息。可靠的消息传递和安全性是两个这样的例子。
另一种可能的解决方案是将大消息分成称为块的较小消息,一次发送一个块,然后在接收端重新构建大消息。应用程序本身可以执行此分块和取消分块,也可以使用自定义通道来执行此操作。分块信道样本显示了如何使用自定义协议或分层信道来对任意大的消息进行分块和去块。
提供的示例下载可用 http://msdn.microsoft.com/en-us/library/aa717050.aspx