bju*_*tus 5 c# memory stream xps package
在我们的应用程序中,我们使用System.IO.Packaging.Package类读取XPS文件.当我们从PackagePart的流中读取时,我们可以从任务管理器中看到应用程序的内存消耗增加.但是,当读取完成后,内存消耗不会回落到从流中读取之前的内存消耗.
为了说明这个问题,我编写了一个简单的代码示例,您可以在独立的wpf应用程序中使用它.
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
_package = Package.Open(@"c:\test\1000pages.xps", FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
private void ReadPackage()
{
foreach (PackagePart part in _package.GetParts())
{
using (Stream partStream = part.GetStream())
{
byte[] arr = new byte[partStream.Length];
partStream.Read(arr, 0, (int)partStream.Length);
partStream.Close();
}
}
}
Package _package;
private void Button_Click(object sender, RoutedEventArgs e)
{
ReadPackage();
}
}
Run Code Online (Sandbox Code Playgroud)
ReadPackage()方法将所有PackagePart对象的流内容读入本地数组.在示例中,我使用了1000页的XPS文档作为包源,以便轻松查看应用程序的内存消耗变化.在我的机器上,独立应用程序的内存消耗从18MB开始,然后在调用该方法后上升到100MB.再次调用该方法可以再次提高内存消耗,但可以回落到100MB.但是,它不再回落到18MB.
有没有人在使用PackagePart时遇到过这种情况?或者我使用它错了?我认为PackagePart的内部实现是缓存读取的数据.
谢谢!
您没有指定如何测量应用程序的“内存消耗”,但也许您正在使用任务管理器?为了更好地了解正在发生的情况,我建议您检查应用程序的一些性能计数器。.NET 堆和通用进程内存性能计数器均可用。
如果您确实想了解应用程序如何使用内存的详细信息,您可以使用Microsoft CLR 探查器。
您所看到的可能是 .NET 堆扩展以容纳非常大的文件的结果。大对象被放置在大对象堆 (LOH) 上,即使 .NET 内存被垃圾回收,空闲内存也永远不会返回给操作系统。此外,LOH 上的对象在垃圾收集期间永远不会移动,这可能会导致 LOH 碎片耗尽可用地址空间,即使有大量可用内存也是如此。
有人在使用 PackagePart 时遇到过这种情况吗?还是我用错了?
如果您想控制包使用的资源,那么您就没有以最佳方式使用它。软件包是一次性的,通常您应该像这样使用它:
using (var package = Package.Open(@"c:\test\1000pages.xps", FileMode.Open, FileAccess.ReadWrite, FileShare.None)) {
// ... process the package
}
Run Code Online (Sandbox Code Playgroud)
在语句结束时,using包消耗的资源要么已经释放,要么可以被垃圾收集。
如果您确实想保留_package表单的成员,您应该在某个时候调用Close()(或IDisposable.Dispose())来释放资源。不建议调用GC.Collect(),也不一定能够回收包所使用的资源。_package无论您多久尝试强制垃圾回收,任何可访问的托管内存(例如包缓冲区)都不会被垃圾回收。