为什么我的表单在尝试加载图像时会抛出OutOfMemory异常?

时间:2012-05-26 20:09:57

标签: c# winforms out-of-memory

我有一个应用程序将带有图像的用户信息保存到数据库中。管理员可以通过不同的表单视图访问已保存的信息。单击列表框项目将显示从数据库中检索到的图像的详细信息。

UserViewDetails.cs:

private void lbEmp_SelectedIndexChanged(object sender, EventArgs e)
{
    try
    {
        if (lbEmp.SelectedIndex != -1)
        {
            em.Emp_ID = Convert.ToInt32(lbEmp.SelectedValue);
            em.SelectById();
            if (!em.EmptyPhoto)
                pbEmp.BackgroundImage = em.Picture;
            else
                pbEmp.BackgroundImage = null;

            txtEmpName.Text = em.Emp_Name;
            txtImagePath.Text = em.ImgPath;
            cmbEmpType.SelectedText = em.EmployeeType;
            cmbCountry.SelectedValue = em.CountryID;
            cmbCity.SelectedValue = em.CityID;
        }
    }
    catch (Exception) { }
}

此表单是从父表单Form1调用的:

Form1.cs中:

try
{
    var vi = new Admin.frmViewEmployeeInfo();
    vi.ShowDialog();
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

这里捕获了“内存不足”异常。怎么了?相同的代码不会在我的另一个应用程序中抛出任何异常。

1 个答案:

答案 0 :(得分:6)

使用Bitmap类时,OutOfMemoryException非常常见。位图可能需要大量内存。遇到麻烦的一种标准方法是调用它的Dispose()方法。在您的代码中不使用Dispose()是您可以在.NET中轻松获得的东西,终结器将在您之后清理。但这往往不适用于位图,因为他们需要很多的非托管内存来存储像素数据,但管理内存非常少。

代码中至少缺少一个Dispose()调用,您没有处理旧的背景图像。修正:

em.SelectById();
if (pbEmp.BackgroundImage != null) pbEmp.BackgroundImage.Dispose();    // <== here
if (!em.EmptyPhoto)
    pbEmp.BackgroundImage = em.Picture;
else
    pbEmp.BackgroundImage = null;

可能在其他地方,我们无法看到如何管理em.Picture。

此外,更难以诊断的是,GDI +在提高准确异常方面相当差。您还可以从包含错误图像数据的文件中获取OOM。你会在this answer找到令人遗憾的行为的理由。