質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.02%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

C#でBitmapをDisposeできずにメモリが増えていくのを対処したい

退会済みユーザー

退会済みユーザー

総合スコア0

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

1回答

0グッド

0クリップ

46126閲覧

投稿2016/09/29 09:43

編集2016/09/29 09:55

C#のBitmapのDisposeについて質問です。

pictureBoxに画像を表示して、Button1を押すと1pixel拡大するというコードを記述しました。

c#

1// Button1クリックイベント 2private void button1_Click(object sender, EventArgs e) { 3 Bitmap img = (Bitmap)pictureBox1.Image; 4 pictureBox1.Image = ScaleBmp(img); 5} 6 7// 元のBitmapを引き数に渡すと1pixel拡大したBitmapを出力する 8private Bitmap ScaleBmp(Bitmap src){ 9 Bitmap bmp = new Bitmap(src.Width + 1, src.Height + 1); 10 using (Graphics g = Graphics.FromImage(bmp)) { 11 g.DrawImage(src, 0, 0, src.Width + 1, src.Height + 1); 12 } 13 return bmp; 14}

このButton1を連続で何回も押すとプロセスメモリがどんどん増えていきます。
ScaleBmp関数の中でBitmapを生成してreturnしているので使用メモリが増えるのは当然なのですが巨大な画像の場合はものすごい勢いで増えていきます。

BitmapをpictureBox1.Imageに渡している場合、DisposeするとエラーになるためにDisposeすることができず、メモリが増えてしまいます。

しばらく放置すると.NetFrameworkが勝手にどこかでGCを実行するので不要になったBitmapが解放されるのですが、Button1を連打すると解放される前にメモリリークを起こしそうで困っています。

button1_Click関数の中の最後にGC.Collect()を実行すればいいのかとは思いますが、Button1を連打する度にGCを呼ぶのもよくないと思ってしまいます。

何か対策はありますでしょうか?
どうぞよろしくお願い致します。

Windows10 + VisualStudio2015 C#

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

hihijiji

2016/09/29 09:55

pictureBox1.Image = ScaleBmp(img); //の後に img.Dispose(); // ←追加 するだけじゃダメですか?
退会済みユーザー

退会済みユーザー

2016/09/30 01:36

ありがとうございます、それで大丈夫でした!

回答1

0

ベストアンサー

これで改善しませんかね?
var oldImage = pictureBox1.Image;
pictureBox1.Image = ScaleBmp(img);
oldImage.Dispose();

投稿2016/09/29 10:00

編集2016/09/30 01:19
ishi9

総合スコア1290

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

退会済みユーザー

退会済みユーザー

2016/09/29 10:18

ありがとうございます。 てっきりScaleBmp関数内のBitmap bmp = new Bitmapで生成しまくっているほうがメモリを増やしているとばかり思っていました・・・。 そちらでメモリは増えなくなりました・・・!
ishi9

2016/09/30 01:12

いや、それで合ってます。メモリの増大分はそれです。 というか考え方的にも手順的にも概ね合ってます。 唯一の問題はここで >>BitmapをpictureBox1.Imageに渡している場合、DisposeするとエラーになるためにDisposeすることができず、メモリが増えてしまいます。 これのせいで開放処理ができなくなってしまっていたのが問題です。 pictureBox1.Image = ScaleBmp(img); これだけだと古いBitmapは参照から外れるだけで開放されません。(いつかはGCによって開放されますが)
退会済みユーザー

退会済みユーザー

2016/09/30 01:35

再度ありがとうございます。 var oldImage = pictureBox1.Image; pictureBox1.Image = ScaleBmp(img); oldImage.Dispose(); ですが、2行目の引数は pictureBox1.Image = ScaleBmp(oldImage); ですよね・・・? それといまいちわからないのですが、ScaleBmp関数内でnewで生成されたBitmapがどこで開放されているのかわかりません・・・。 ScaleBmp関数内で生成されたBitmapはpictureBox.Imageに渡りますが、ボタンを再び押すとまた生成されます。つまりその前に生成されたBitmapはどこで開放されているのでしょうか?
ishi9

2016/09/30 02:29

>>pictureBox1.Image = ScaleBmp(oldImage); すいません、そうでした。 >>ScaleBmp関数内で生成されたBitmapはpictureBox.Imageに渡りますが、ボタンを再び押すとまた生成されます。つまりその前に生成されたBitmapはどこで開放されているのでしょうか? 以前のコードだと一切開放されていません。完全放置状態です。 そして、それが今回のメモリ増大の原因です。 例えば、例を挙げると、こんな感じでしょうか void Func () { Bitmap image1 = (Bitmap)pictureBox1.Image; var image2 = ScaleBmp(image1); pictureBox1.Image = image2; var image3 = ScaleBmp(image2); pictureBox1.Image = image3; ・ ・ 以下繰り返し } こんな感じでimage1~10000000と処理を増やしていったらどうなるでしょうか? 当然、すぐにメモリオーバーしますよね?image2も3もそれ以降も全部 実際にBitmap持ってるわけですから。 前の処理はまさにこんな感じでした。 それを今回はこのように直しました。 void Func () { Bitmap image1 = (Bitmap)pictureBox1.Image; var image2 = ScaleBmp(image1); pictureBox1.Image = image2; image1.Dispose(); // ※1 var image3 = ScaleBmp(image2); pictureBox1.Image = image3; image2.Dispose(); // 上に同じ ・ ・ 以下繰り返し } ※1 image1.Dispose(); // pictureBox1.Imageはimage2に新しく置き換わってimage1を使わなくなったので、古いイメージであるimage1は開放する
退会済みユーザー

退会済みユーザー

2016/09/30 04:28

非常にわかりやすいご説明をありがとうございます! とても納得できました! Idisposableのあるオブジェクトは開放をきちんとしないとどんどんメモリが増えていきますね・・・。 今回の件で理解できましたので本当に助かりました。 ありがとうございます!

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.02%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。