您的代码中至少有 2 个完全独立的问题导致其出现故障。
问题 #1:GDI+ 错误
这是一个反复出现的问题,在生态系统的各个地方不断涌现。我有它,我设法修复它,现在我不记得具体如何了。我试图复制您的问题,但未能收到失败消息。
我建议你检查这个线程:http ://forums.asp.net/t/624305.aspx/1
这里有些人很高兴地通过以下方式克服了这个问题:
- 确保他们在处理其他绘图之前处理了所有的 Bitmap 实例
- (有趣的一个):做一个GC.Collect()(可能在每次位图渲染之后)
这不是我想尝试帮助您回答的主要原因。看来你已经做了(你说你做了)我通常做的所有事情,以确保我不会最终陷入这种情况(安全、信任等)。此外,您自己进行的清理工作超出了需要(阅读我的答案时您会发现有点太多了)。
我发现您的代码有第二个问题,您可能不知道。通过在我自己的 VS 环境中简单地解决这个问题,我成功地渲染了位图(在 IIS 7 和 Express 以及 ASP 开发服务器中)。
很有可能通过在应用程序代码中重新组织一些东西,您将设法解决问题 #1。所以:请查看我对问题 #2 的看法。
问题#2:不能同时处理和返回流
您不能返回刚刚创建和处置的流,例如:
public static Stream SomeMethod() {
using (MemoryStream stream = new MemoryStream()) {
// write something to the stream
return stream;
}
}
我真的不明白那段代码在 ASP.NET 开发服务器中是如何工作的。我在这里要指出的问题是您的代码总是会抛出 ObjectDisposedException (无论您是将代码作为服务运行还是在交互式用户空间中运行):
谁关闭了流?using语句的终止。
问题 #2 的可能解决方案
这个特定问题的快速解决方案(可能会占用比您预期的更多的内存)是让您的方法返回一个 byte[] 而不是一个流。
public static byte[] SomeMethod() {
using (MemoryStream stream = new MemoryStream()) {
// ... create bitmap and render things ...
// write something to the stream
bitmap.Save(stream, ImageFormat.Png);
return stream.ToArray();
}
}
允许我自己对您的应用程序需求做出假设,我会说这个其他解决方案可能会更好:
如果您希望将这些生成的图表图像以<img>标记返回到 Web 浏览器,并且您通过 ASP.NET 通用处理程序来完成此操作,那么您可以将 OutputStream 传递给当前 WebResponse对您的绘图方法,而不是从中获取结果 byte[] (或 Stream),如下所示:
在 HTML 中:
<img src="path/Foo.ashx" alt="chart" ... etc ... />
在应用程序中:
public class Foo : IHttpHandler {
public void ProcessRequest(HttpContext context) {
context.Response.ContentType = "application/octet-stream";
Stream alreadyExistingStream = context.Response.OutputStream;
Etc.SomeMethod(stream);
}
}
public class Etc {
public static void SomeMethod(Stream stream) {
// There used to be a using here that would create a stream
// simply because the parameter name **stream** is the same as the former local var's name
// the instructions that do the drawing of things
// + saving of the resulting Bitmap **to** the stream
// keep on compiling without any problems
// draw things to a bitmap
// write the bitmap to the stream
bitmap.Save(stream, ImageFormat.Png);
// returning stuff is not needed anymore
// This used to be the time and place where the stream would be disposed
// and it's resources given back to the community
}
}