c# – Bitmap.Save在几个小时后停止工作
在过去几个月中,我们已经开始面临一个问题,即System.Drawing.Bitmap.Save(字符串文件名)方法在服务器运行几个小时后停止工作.它开始失败的小时数与服务器负载成正比.
这个调用所涉及的代码几年来一直运行良好,它从用户获取和图像,调整大小并将其保存到磁盘.该应用程序是一个开发.Net Framework 3.5的ASP.Net应用程序. 当对Bitmap.Save的调用失败时,它会引发臭名昭着的异常:
我一直在阅读很多关于该异常的帖子,我完全清楚在许多不同的情况下会引发这个异常.这是一个通用的异常,由于许多不同的原因(即,当应用程序没有写入文件夹的permisison,当代码试图将图像保存在它正在读取的同一文件中时,等等),但是没有这些情况就是我们的情况. 当我们认识到该方法失败时,我们刚刚发布了我们的应用程序的新版本,所以我们最初认为错误可能在我们的代码中(尽管该部分没有被更改,我们认为我们已经改变了其他干扰的东西,产生错误),但我们调查得越多,我们就越不了解错误发生的时间. 同样重要的是,在出现错误的同时,我们还使用最新的Windows更新更新了我们的服务器,在那里我还看到了两个可疑的: KB2929755 http://support.microsoft.com/kb/2929755/en-us KB2957503 http://support.microsoft.com/kb/2957503/en-us 我的感觉是服务器上的某些东西没有被释放,就像某些代码泄漏处理程序或内存一样,并且在某些时候服务器耗尽它们并且不能再保存Bitmap.出现错误时,从应用程序的任何部分对Bitmap.Save的任何调用都会引发该异常.重新启动IIS会解决问题直到下一次,但是,如果我们只重新启动应用程序池,则情况并非如此. 如果它可以以任何方式提供帮助,我们使用HiQPdf库(版本6.8.0.0)将一些HTML文档转换为PDF.此工具为每次转换创建一个新进程,并在完成时将其终止,并假设以适当的方式释放所有使用的资源. 是否有人遇到任何类似的问题? 有人在描述Windows更新方面有任何问题吗? 我还忘了提到我们尝试使用WPF API而不是GDI调整图像大小,但我们遇到了同样的问题,几个小时后服务器开始引发错误(虽然这次消息是ExcepcióndeHRESULT:0x88982F8A),所以我们将它还原为原始代码. 任何帮助,将不胜感激! 编辑: 实际上,使图像调整大小和保存的代码如下.所有变量都在使用块内,但是对于将图像映射到Bitmap,我假设它仍然被处理掉: using (Image originalLogo = Image.FromStream(fuLogo.PostedFile.InputStream)) { using (Image resizedLogo = ImageUtil.ResizeImage(originalLogo,maxWidth,maxHeight)) { ((System.Drawing.Bitmap)resizedLogo).Save(newFilePath); } } 铸造到Bitmap是否需要创建一个中间变量来强制它的处置,或者不需要? using (Image originalLogo = Image.FromStream(fuLogo.PostedFile.InputStream)) { using (Image resizedLogo = ImageUtil.ResizeImage(originalLogo,maxHeight)) { using (Bitmap bitmap=((System.Drawing.Bitmap)resizedLogo)) { bitmap.Save(newFilePath); } } } 谢谢, 编辑: 我粘贴在ResizeImage方法的代码下面: public static System.Drawing.Image ResizeImage(System.Drawing.Image originalImage,int maxWidth,int maxHeight) { int imgWidth = originalImage.Width; int imgHeight = originalImage.Height; if (originalImage.Height<maxHeight && originalImage.Width<maxWidth) return originalImage; double widhtRatio = ((double)maxWidth) / ((double)imgWidth); double heightRatio = ((double)maxHeight) / ((double)imgHeight); int targetWidth,targetHeight; if (widhtRatio < heightRatio) { targetWidth = (int)(imgWidth * widhtRatio); targetHeight = (int)(imgHeight * widhtRatio); } else { targetWidth = (int)(imgWidth * heightRatio); targetHeight = (int)(imgHeight * heightRatio); } //Not all pixel formats are supported,therefore,using the //originalImage pixel format raises an exception if the pixel format is not supported. //By not specifying it,the Bitmap constructor will use one compatible with the FromImage method. //For more info see: http://forums.asp.net/p/1195630/2066153.aspx // Image resizedImage = new Bitmap(targetWidth,targetHeight,originalImage.PixelFormat); System.Drawing.Image resizedImage = new Bitmap(targetWidth,targetHeight); using (Graphics riGraphics = Graphics.FromImage(resizedImage)) { riGraphics.CompositingQuality = CompositingQuality.HighQuality; riGraphics.SmoothingMode = SmoothingMode.HighQuality; Rectangle rectangle = new Rectangle(0,targetWidth,targetHeight); riGraphics.DrawImage(originalImage,rectangle); riGraphics.Flush(); } return resizedImage; } 解决方法
我为你在黑暗中绝对刺伤:
在您的应用程序代码中,在调用Save()之后,位图对象是使用还是显式处理?我已经看到很难跟踪过去在处理IDisposible对象时因内存泄漏引起的异常,当它们被重复使用并且没有得到妥善处理时.这些情况似乎总是像您所描述的那样间歇性,并且在实现解决方案之前就像调用Bitmap.Dispose()一样简单,或者在重新考虑因素或代码更新期间意外删除之后将其放回原处. ). 但不太可能,因为听起来你的代码在应用Windows更新之前有效…我以为我会把它扔出去. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |