免责声明:我的回答可能仅与 WPF 之前的 .NET 相关(但相同的概念适用于两者)。
标题问题的答案是“两者”。 System.Drawing 命名空间包含一个方便的 Bitmap 类,它本质上是一个 DIB(或设备独立位图)。 Bitmap 类包含一个 GetHbitmap 方法,该方法在内存中创建原始 DIB 的 DDB(或设备相关位图)副本并返回它的句柄。
可以将 DDB 句柄选择到设备上下文中(这使您可以使用超快的BitBlt API 方法)。或者,您一开始就永远无法创建 DDB,并使用纯 .Net(最好的方法,IMO)来完成所有图形操作。 GetHbitmap 是一种相对危险的方法,因为您必须在它返回的句柄上调用 DeleteObject 以便在完成后释放它的内存(这是我能想到的唯一示例。 需要一个 PInvoked API 调用才能正常运行)。此外,由于该方法返回一个IntPtr,程序员往往没有意识到当它被调用时,操作系统必须开辟另一块大小与原始 .Net (DIB) 位图相等的内存。
所以答案是:.Net 使用 DIB,但必要时可以使用 DDB。或者更糟糕的是,当不是必要时。实际上,我继承了不止一个使用 GetHBitmap 而没有匹配的 DeleteObject 调用的 .NET Web 应用程序,从而产生了一次长时间的内存泄漏。
不过,您有一个更广泛的问题,即:在服务器上运行的 .Net 应用程序能否可靠地处理大量大型图像文件而不会导致服务器崩溃?答案是肯定的,只要您真正了解 .NET 框架在幕后通过图像处理做什么。 .NET 图形类封装了许多远离程序员的可怕细节,在某些方面这有点糟糕,因为它使程序员不太可能了解真正发生的事情。
编辑:忘记包含来自MSDN的重要免责声明:
注意
System.Drawing 中的类
不支持使用命名空间
在 Windows 或 ASP.NET 服务中。
尝试使用这些类
在这些应用程序类型之一中
可能会产生意想不到的问题,例如
由于服务性能下降和
运行时异常。
翻译:“你可能会搞砸这件事 - 不要说我们没有警告过你”。从根本上说,这是一个合理的建议,因为这些类——虽然非常强大和有用——也很危险。消耗一些资源并且无法正确释放它,或者以导致大量内存消耗的方式使用类是非常容易的。有时这些问题在桌面应用程序中并不大,但在同时处理多个请求的负载很重的 Web 服务器中,它可能会成为一个大问题。
我认为在这种情况下可以安全地使用它们,但是,或者换一种说法,如果您尝试在网络服务器同时。但是,我会确保在投入生产之前对我的网站代码进行了大量负载测试。
更新1:以下引用(带有link)适用于.NET Compact Framework中的位图,我认为它不适用于完整的框架(我主要包括在这里供一般参考 - 即有一天我可以自己再次找到它):
这里有一些更深入的信息
[.NetCF] 位图的分配方式。
有两条主要途径
分配可能会影响
内存已分配,但最后
有与指示相同的问题
以上。
- 接受流的位图构造函数
作为参数[即从文件加载]
- 这将构造一个 DIB
- DIB 被分配到应用程序进程虚拟内存之外
(VM) 地址空间
- 位图构造函数
将高度/宽度作为
参数
- 这将构建一个 DDB
- DDB 由驱动程序分配,通常在 gwes.exe 或可能
在专用的视频 RAM 中。这会
实际使用物理和虚拟
不在进程 VM 中的内存
空间。
简而言之,我们有 2 种不同类型的
我们运行时中的位图有不同的
性能和分配
特征。 DDB 通常是
更快地操纵和绘制
屏幕比 DIB,但它们是
在外部存储器中构建
可能导致分配的空间
混乱并导致性能
调用 LockBits 或 Save to be
慢点。如果需要 DIB 并且您
希望根据宽度构建它
和高度,我们提供了一个函数
构造一个具有宽度的位图,
指定的高度和像素格式。
该函数将构造一个 DIB
而不是 DDB。
更多信息(仍然只是关于 .NetCF 位图):
http://blog.opennetcf.com/ctacke/PermaLink,guid,987041fc-2e13-4bab-930a-f79021225b74.aspx
更新 2: 一些与完整框架中的 .NET 位图相关的链接(摘要在底部):
http://www.dotnetmonster.com/Uwe/Forum.aspx/dotnet-performance/1187/Graphics-FromImage-Process-memory-usage
http://www.netframeworkdev.com/common-language-runtime/memory-issues-with-systemdrawingbitmap-30879.shtml
http://www.west-wind.com/WebLog/posts/8230.aspx
http://www.tech-archive.net/Archive/DotNet/microsoft.public.dotnet.framework.drawing/2005-06/msg00171.html
总结:我认为这个问题很难回答,因为基本上,这个(Bitmap 使用的内存的实际位置)是一个内部 .NET 实现细节,大部分没有记录在好理由。因为看起来你现在不能确定位图的内存在哪里,而且你肯定不能确定它将来会在哪里,我不得不说 MSDN 可能不是在开玩笑,他们说:
注意
System.Drawing 中的类
不支持使用命名空间
在 Windows 或 ASP.NET 服务中。
尝试使用这些类
在这些应用程序类型之一中
可能会产生意想不到的问题,例如
由于服务性能下降和
运行时异常。