2

ユーザー情報と画像をデータベースに保存するアプリケーションがあります。管理者は、別のフォーム ビューから既に保存されている情報にアクセスできます。リストボックス項目をクリックすると、データベースから取得した画像とともに詳細が表示されます。

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);
}

ここで、「メモリ不足」の例外がキャッチされます。何が起こっている?私の別のアプリケーションでは、同じコードは例外をスローしません。

4

1 に答える 1

6

OutOfMemoryException は、Bitmap クラスを使用する場合によく発生します。ビットマップは大量のメモリを必要とする場合があります。トラブルに巻き込まれる標準的な方法の 1 つは、Dispose() メソッドの呼び出しをずさんにすることです。コードで Dispose() を使用しないことは、.NET で簡単に解決できることです。ファイナライザーは後でクリーンアップします。しかし、ビットマップでは、ピクセル データを格納するために大量のアンマネージド メモリが必要ですが、マネージド メモリはほとんど必要ないため、うまく機能しない傾向があります。

コードに少なくとも 1 つの 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 を取得することもできます。この回答で、その残念な行動の理由を見つけることができます。

于 2012-05-26T20:38:18.347 に答える