C# .NET Frameworkを利用してスライドショーなど複数の画像を切り替えながら継続的に表示する場合、適切にDisposeしてあげないとメモリリークを起こしてしまいます。過去にこの件を調べたところDisposeを書く場所を間違えたことがあったのでここに書き残します。今回は手っ取り早く多くの画像の切り替えを行うためOnPaintに入れて画像を切り替えていきます。
pathlstには画像のpathが入っていてcurrentの数値を変えることで画像を切り替えます。
###なにもDisposeしない場合
Form1.cs
protected override void OnPaint(PaintEventArgs e)
{
if (current >= pathlst.Count())
{
current = 0;
}
Image img = Image.FromFile(pathlst[current]);
pictureBox1.Image = img;
pictureBox1.Update();
current++;
Invalidate();
}
###Image.FromFileの代わりにFileStreamを使う
Form1.cs
System.IO.FileStream fs1 = new System.IO.FileStream(pathlst[current],
System.IO.FileMode.Open, System.IO.FileAccess.Read);
pictureBox1.Image = System.Drawing.Image.FromStream(fs1);
fs1.Close();
たまにGCが呼ばれたりしているのでひどいリークは起こしていないように思えます。
###PictureBoxのImageをDisposeする
Form1.cs
if (pictureBox1.Image != null)
{
pictureBox1.Image.Dispose();
}
Image img = Image.FromFile(pathlst[current]);
pictureBox1.Image = img;
PictureBoxに前の画像が入っていた場合その画像をDisposeしてあげればリークを起こしません。はじめは22MB程度で、18秒経過後も30MBあたりに収まっています。
Disposeは後に書いてはダメで
Form1.cs
System.IO.FileStream fs1 = new System.IO.FileStream(pathlst[current], System.IO.FileMode.Open, System.IO.FileAccess.Read);
pictureBox1.Image = System.Drawing.Image.FromStream(fs1);
fs1.Close();
pictureBox1.Image.Dispose();
前に書いてもnullかどうか調べてからではないとエラーを起こします。
Form1.cs
pictureBox1.Image.Dispose();
System.IO.FileStream fs1 = new System.IO.FileStream(pathlst[current], System.IO.FileMode.Open, System.IO.FileAccess.Read);
pictureBox1.Image = System.Drawing.Image.FromStream(fs1);
fs1.Close();