C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[6]: 画像処理を行うときのBitmap等のDisposeについて


(過去ログ 82 を表示中)

[トピック内 12 記事 (1 - 12 表示)]  << 0 >>

■48931 / inTopicNo.1)  画像処理を行うときのBitmap等のDisposeについて
  
□投稿者/ クメール (1回)-(2010/04/16(Fri) 21:15:05)

分類:[VB.NET/VB2005 以降] 

VB2008を使用して画像処理に挑戦しようと思っていますが(VBしか分からないので)、
Webサイトに掲載されている画像処理のサンプルを見ると、例えば以下のようになっています。

Private Sub BitmapTest(ByVal iWidth as Integer, ByVal iHeight as Integer)
'Bitmapの作成
Dim bmp As New Bitmap(iWidth, iHeight)

'画像処理
Dim g As Graphics = Graphics.FromImage(bmp)
(途中略)
g.Dispose()

'任意の処理
(途中略)
bmp.Dispose()
End Sub

ここで質問なのですが、上の例では処理に使用したBitmapやGraphicsをわざわざDispose()しています。
BitmapTestサブルーチン内のローカル変数なので、BitmapTestサブルーチンを抜けたら
自動的にメモリを解放してくれるのではないかとシロウト考えをしてしまうのですが、
これはDispose()しなければならないのでしょうか?
参照変数だからなのでしょうか?
もしDispose()しないとどうなるのでしょうか?
VBの初歩的なことしか理解していないので、どうぞ忌憚ないご意見をよろしくお願いします。
引用返信 編集キー/
■48937 / inTopicNo.2)  Re[1]: 画像処理を行うときのBitmap等のDisposeについて
□投稿者/ Azulean (548回)-(2010/04/17(Sat) 00:22:20)
No48931 (クメール さん) に返信
> ここで質問なのですが、上の例では処理に使用したBitmapやGraphicsをわざわざDispose()しています。
> BitmapTestサブルーチン内のローカル変数なので、BitmapTestサブルーチンを抜けたら
> 自動的にメモリを解放してくれるのではないかとシロウト考えをしてしまうのですが、
> これはDispose()しなければならないのでしょうか?
Dispose をするべきものと設計されているのであれば、基本的に「しなければならない」と考えておくと良いと思います。
(すべてのクラスにあるわけではありません)

> 参照変数だからなのでしょうか?
いいえ。
参照変数だからとは限りません。

> もしDispose()しないとどうなるのでしょうか?
対象によります。
そのクラスによって使われていたメモリの解放が遅くなるかもしれませんし、使っていたファイルに再度読み書きをしようとしても例外が発生する(エラーになる)かもしれません。
引用返信 編集キー/
■48939 / inTopicNo.3)  Re[1]: 画像処理を行うときのBitmap等のDisposeについて
□投稿者/ よねKEN (474回)-(2010/04/17(Sat) 00:36:16)
2010/04/17(Sat) 00:38:47 編集(投稿者)

No48931 (クメール さん) に返信
> BitmapTestサブルーチン内のローカル変数なので、BitmapTestサブルーチンを抜けたら
> 自動的にメモリを解放してくれるのではないかとシロウト考えをしてしまうのですが、
> これはDispose()しなければならないのでしょうか?

Disposeメソッドで行われる主な処理は、
そのオブジェクトが保持しているアンマネージリソースの解放で、
メモリの解放とは別のものです。

アンマネージリソースというのは、すごく大まかに言うとOSの管理下にある有限の資源全般です。
ウィンドウのハンドルであったり、ファイルのハンドルであったり、
クラスごとに何のアンマネージリソースを保持しているかは異なります。
※ハンドル … OSが何か(ウィンドウやらファイルやら)を管理するために採番する番号
 解放するまで他で利用できなかったりして困る場合があるもの。

> 参照変数だからなのでしょうか?

IDisposableインタフェースを実装しているクラスかどうかで判断できます。

引用返信 編集キー/
■48944 / inTopicNo.4)  Re[1]: 画像処理を行うときのBitmap等のDisposeについて
□投稿者/ 魔界の仮面弁士 (1627回)-(2010/04/17(Sat) 10:31:04)
No48931 (クメール さん) に返信
> 自動的にメモリを解放してくれるのではないかとシロウト考えをしてしまうのですが、
確かに最終的には自動でも解放されます。しかしながら「自分で作成したオブジェクト」であれば
できるだけ早期に「自分で解放すべき」です。逆に言うと、自分が管理している物で無い場合には、
勝手に Dispose すべきではありません(他の箇所でまだ使われるかも知れませんから)。

たとえば、『CreateGraphics()』で作成した Graphics は Dispose が必要ですが、
Paint イベント中で『e.Graphics』で得た Graphics は Dispose してはいけません。

あるいは、『New Pen(Color.Red)』で生成した Pen は Dispose が必要ですが、
『Pens.Red』で得た Pen は Dispose してはいけません。


> これはDispose()しなければならないのでしょうか?
Dispose メソッド(IDisposable.Dispose)を実装したクラスというのは、多くの場合、
OS がもつ有限の資産をカプセル化しています。(よねKENさんも書かれていますね)
それゆえ解放されるまでは、他のアプリがその資源を利用できない(あるいは編集できない)状態に
なってしまう可能性があります。

なお、Using ブロックが使える場合は、Dispose よりも Using を使った方が安全です。


> もしDispose()しないとどうなるのでしょうか?
Azulean さんの回答と被りますが、ケースバイケースです。クラスによって異なりますが、
現象が分かりやすいのは FileStream クラスだと思います。

たとえば、複数のファイルを順次表示していくアプリがあったとしましょう。

このアプリが、ファイルを Close や Dispose せずに、自動解放に任せたままに
していたらどうなるでしょうか。

その場合他のアプリは、そのファイルが閉じられるまで削除も編集もできないという
事態になってしまうわけです。もちろん、いつかは解放されるので、その後であれば
編集できるようになりますが、解放されるタイミングが不定では都合が悪いですよね。
引用返信 編集キー/
■48948 / inTopicNo.5)  Re[2]: 画像処理を行うときのBitmap等のDisposeについて
□投稿者/ クメール (2回)-(2010/04/17(Sat) 20:46:25)
みなさん、解説ありがとうございました。
ただ、以下のような疑問が残ります。

Private Sub Test()
Dim bitmap1 As New Bitmap(画像ファイル名)
'(任意の処理)
Dim bitmap2 As New Bitmap(bitmap1, bitmap1.Width/2, bitmap1.Height/2)
'(以下、処理)
End Sub

という場合、bitmap1はファイルよりビットマップを参照しているので、
Dispose()しないとリソース解放されるまでファイルアクセスが制限されるということは理解できますが、
bitmap2はDispose()しないことにより何か弊害はあるのでしょうか?
(ちなみに、bitmap2はこのSub Test()外で参照されることはありません。)
引用返信 編集キー/
■48949 / inTopicNo.6)  Re[3]: 画像処理を行うときのBitmap等のDisposeについて
□投稿者/ .SHO (1307回)-(2010/04/17(Sat) 21:15:00)
No48948 (クメール さん) に返信
> みなさん、解説ありがとうございました。
> ただ、以下のような疑問が残ります。
>
> Private Sub Test()
> Dim bitmap1 As New Bitmap(画像ファイル名)
> '(任意の処理)
> Dim bitmap2 As New Bitmap(bitmap1, bitmap1.Width/2, bitmap1.Height/2)
> '(以下、処理)
> End Sub
>
> という場合、bitmap1はファイルよりビットマップを参照しているので、
> Dispose()しないとリソース解放されるまでファイルアクセスが制限されるということは理解できますが、
> bitmap2はDispose()しないことにより何か弊害はあるのでしょうか?
> (ちなみに、bitmap2はこのSub Test()外で参照されることはありません。)

それは、ただの屁理屈です。
絶対に Dispose() しないとダメとは誰も言ってないです。

引用返信 編集キー/
■48951 / inTopicNo.7)  Re[3]: 画像処理を行うときのBitmap等のDisposeについて
□投稿者/ 渋木宏明(ひどり) (1305回)-(2010/04/17(Sat) 23:27:39)
渋木宏明(ひどり) さんの Web サイト
> bitmap2はDispose()しないことにより何か弊害はあるのでしょうか?

変数 bitmap2 が指し示してた Bitmap クラスのインスタンスが GC によって回収(同時に Bitmap.Dispose() 呼び出しが行われていない場合、Bitmap.Dispose() 呼び出しが行われます)までの期間、そのインスタンスが内包している GDI+ のビットマップオブジェクト(そして、それは OS レベルの BITMAP オブジェクトを内包します)が居残ります。

読み込まれたビットマップが大きなものであった場合、それが解放されるまでの間、読み込み可能なビットマップの枚数が制限されたり、大きなビットマップの読み込みに失敗する可能性があります。

短い期間内に Test() が頻繁に呼び出されるようなケースでは、不具合として発現しやすいです。



引用返信 編集キー/
■48953 / inTopicNo.8)  Re[4]: 画像処理を行うときのBitmap等のDisposeについて
□投稿者/ クメール (3回)-(2010/04/18(Sun) 00:35:24)
No48951 (渋木宏明(ひどり) さん) に返信
> 変数 bitmap2 が指し示してた Bitmap クラスのインスタンスが GC によって回収(同時に Bitmap.Dispose() 呼び出しが行われていない場合、Bitmap.Dispose() 呼び出しが行われます)までの期間、そのインスタンスが内包している GDI+ のビットマップオブジェクト(そして、それは OS レベルの BITMAP オブジェクトを内包します)が居残ります。

渋木宏明様、解説ありがとうございました。
では、例えば、Test2(ByVal _bitmap As Bitmap)という、引数にBitmapを指定するサブルーチンがあり、
Test()サブルーチンでこれを呼び出す場合、理想としては

Private Sub Test()
Dim bitmap1 As New Bitmap(画像ファイル名)
'(任意の処理)
Dim bitmap2 As New Bitmap(bitmap1, bitmap1.Width/2, bitmap1.Height/2)
Test2(bitmap2)
'(以下、処理)
bitmap2.Dispose()
bitmap1.Dispose()
End Sub

とすべきでしょうが、これを、bitmap2変数を用意せず、

Private Sub Test()
Dim bitmap1 As New Bitmap(画像ファイル名)
'(任意の処理)
Test2(New Bitmap(bitmap1, bitmap1.Width/2, bitmap1.Height/2))
'(以下、処理)
bitmap1.Dispose()
End Sub

というやり方だと、Test2呼び出し時の引数をDispose()する機会がないので、
これあまり推奨されないのでしょうか?
うまく理解できなくて申し訳ありませんが、がんばって理解するよう努力しますのでよろしくお願いします。
引用返信 編集キー/
■48955 / inTopicNo.9)  Re[5]: 画像処理を行うときのBitmap等のDisposeについて
□投稿者/ よねKEN (475回)-(2010/04/18(Sun) 01:03:25)
No48953 (クメール さん) に返信
> これあまり推奨されないのでしょうか?

そうですね。前者のやり方(Disposeメソッドを呼び出すために変数を用意する)のほうがよいです。さらにUsingステートメントを使った記述にするとさらによいです。

Using ステートメント
http://msdn.microsoft.com/ja-jp/library/htd05whh(VS.80).aspx

引用返信 編集キー/
■48956 / inTopicNo.10)  Re[6]: 画像処理を行うときのBitmap等のDisposeについて
□投稿者/ クメール (4回)-(2010/04/18(Sun) 07:22:04)
No48955 (よねKEN さん) に返信
よねKEN様、ご回答ありがとうございました。
確かに、System.IO.FileStreamやSystem.IO.StreamWriter/Readerは、Usingを使用しています。
これは、いちいち明示的にCloseしなくても、使用後確実にされるということで使用していますので、
同様に考えればよいですね。

みなさん、色々とご意見ありがとうございました。勉強になりました。
今後ともよろしくお願い申し上げます。
解決済み
引用返信 編集キー/
■48957 / inTopicNo.11)  Re[5]: 画像処理を行うときのBitmap等のDisposeについて
□投稿者/ 渋木宏明(ひどり) (1306回)-(2010/04/18(Sun) 13:00:59)
渋木宏明(ひどり) さんの Web サイト
> これあまり推奨されないのでしょうか?

されないです。

Bitmap クラスのインスタンス管理が適切でないです。

引用返信 編集キー/
■48961 / inTopicNo.12)  Re[6]: 画像処理を行うときのBitmap等のDisposeについて
□投稿者/ クメール (5回)-(2010/04/18(Sun) 16:45:11)
No48957 (渋木宏明(ひどり) さん) に返信
渋木宏明様、コメントありがとうございました。
とりあえず、よねKEN様のご回答を踏まえ、以下のようにしようと思います。

Private Sub Test()
    Using bitmap1 As New Bitmap(画像ファイル名)
    '(任意の処理)
        Using bitmap2 As New Bitmap(bitmap1, bitmap1.Width/2, bitmap1.Height/2)
            Test2(bitmap2)
        End Using
        '(以下、処理)
    End Using
End Sub

みなさん、色々とご意見ありがとうございました。勉強になりました。
とりあえず、また解決済みをつけますが、なにかコメントがありましたらお願い申し上げます。

p.s.
今回は図表モードというもので投稿します。
今まではソースがみづらくてごめんなさい。

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -