【发布时间】:2016-03-15 18:48:26
【问题描述】:
遇到这个错误:
“System.OutOfMemoryException”类型的异常发生在 System.Drawing.dll 但未在用户代码中处理
附加信息:内存不足。
它发生在DrawImage调用的以下方法中
/// <summary>
/// Resize the image to the specified width and height.
/// </summary>
/// <param name="image">The image to resize.</param>
/// <returns>The resized image.</returns>
public Bitmap ResizeImage(Image image, System.Drawing.Size newSize)
{
var destRect = new Rectangle(0, 0, newSize.Width, newSize.Height);
var destImage = new Bitmap(newSize.Width, newSize.Height);
destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (var graphics = Graphics.FromImage(destImage))
{
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
using (var wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
}
}
return destImage;
}
我不知道为什么会这样,我多次调用这个方法,结果被转换成 Base64 字符串并存储在 ObservableCollection 中。
/// <summary>
/// Convert Image and Resize
/// </summary>
/// <param name="loc"></param>
/// <returns></returns>
public async Task<string> GenerateThumbnailBinary(string loc)
{
return await Task<string>.Factory.StartNew(() =>
{
Image image = Image.FromFile(loc, true);
// Figure out the ratio
double ratioX = (double)Properties.Settings.Default.ThumbnailWidth.Width / (double)image.Width;
double ratioY = (double)Properties.Settings.Default.ThumbnailWidth.Height / (double)image.Height;
// use whichever multiplier is smaller
double ratio = ratioX < ratioY ? ratioX : ratioY;
System.Drawing.Size newSize =
new System.Drawing.Size(
(int)(image.Width * ratio),
(int)(image.Height * ratio));
Image resized = ResizeImage(image, newSize);
return ImageToBase64(resized, ImageFormat.Jpeg);
});
}
我还通过绑定到集合并使用转换器将 Base64 字符串转换回位图,将每个字符串显示为图像,这只是为了让 UI 显示已转换的内容。
我的问题从哪里开始?当我在 UI 上显示图像并使用转换器将字符串转换为图像时,我是否会尝试在内存中存储太多图像?
下图中的高点在运行方法循环时很明显,但它似乎仍然比方法运行结束前高,这有帮助吗?
编辑: 这是启动任务并运行方法的循环。
// Generate List of images to upload
var files = Directory.EnumerateFiles(sel.Name, "*.*", SearchOption.AllDirectories)
.Where(s => s.EndsWith(".jpeg") ||
s.EndsWith(".jpg") ||
s.EndsWith(".png") ||
s.EndsWith(".JPG"));
int b = 1;
if (files.Count() > 0)
{
/// <summary>
/// Resize Images
/// </summary>
/// Set current Task first
UploadTask = Steps[0].Message;
try
{
foreach (string item in files)
{
// Generate new name
string oldname = Path.GetFileNameWithoutExtension(item);
string newName = Common.Security.KeyGenerator.GetUniqueKey(32);
string t = await GenerateThumbnailBinary(item);
ImageUploadObjects.Add(
new ImageUploadObject { OldName = oldname,
NewName = newName,
ByteImage = t });
UploadProgress = (int)Math.Round((double)(100 * b / files.Count()));
b++;
}
// Complete
Steps[0].Complete = true;
}
catch(Exception e)
{
Steps[0].Error = e.InnerException.ToString();
}
/// <summary>
/// Move full resoluation images
/// </summary>
/// Set current Task first
UploadTask = Steps[1].Message;
try
{
foreach (string item in files)
{
}
// Complete
Steps[1].Complete = true;
}
catch (Exception e)
{
Steps[1].Error = e.InnerException.ToString();
}
}
}
编辑:
如何判断内存是否仍在使用?我在下面添加了另一张图片,第一个快照是在我执行该方法之前,最后一个是它完成时,2 - 4 是它正在运行的时候
【问题讨论】:
-
在处理位图和绘图时,由于很多原因,您可能会收到 OutOfMemoryException,例如 stackoverflow.com/questions/6506089/…(我并不是说这是重复的,只是为了看看)。跨度>
-
您需要处理一些变量(图像和调整大小)。通过调用
.Dispose()或使用using关键字。注意不要同时调用这个方法太多次。 -
图片大小是否合理?
-
我会确保我处理变量,是的,大小都是一样的
标签: c# winforms memory-leaks