3

を使用してロードしImage、画像を調べて画像に関する情報を取得しています。ただし、これを行う過程で、画像の一部が消えるという奇妙な動作に気付きました。多くのデバッグの後、私は最終的にこれが廃棄されていることが原因であることがわかりました。byte[]MemoryStreamProperyItemsPropertyItemsMemoryStream

MemoryStream ms0 = new MemoryStream(imageBytes);
Image img0 = Image.FromStream(ms0);
Console.Out.WriteLine("Without using, Image propertyIDs: ");
foreach (int itemId in img0.PropertyIdList)
    Console.Out.Write(itemId + ", ");
Console.Out.Write("\n");

Image img1 = null;
using (MemoryStream ms1 = new MemoryStream(imageBytes))
{
    img1 = Image.FromStream(ms1);
}
Console.Out.WriteLine("Outside using, Image propertyIDs: ");
foreach (int itemId in img1.PropertyIdList)
    Console.Out.Write(itemId + ", ");
Console.Out.Write("\n");

出力:

Without using, Image propertyIDs: 
254, 256, 257, 258, 259, 262, 269, 273, 274, 277, 278, 279, 282, 283, 284, 296, 
Outside using, Image propertyIDs: 
254, 256, 257, 258, 259, 262, 274, 277, 278, 284, 296, 

したがって、少なくとも一部の はPropertyItemsの内容に直接裏打ちされているようでMemoryStreamあり、解決策はそれを破棄しないことですか、それとも間違っていますか?

この問題をデバッグする過程で、ブロック内のPropertyIdList(または画像に関連するもの) にアクセスすると、 が破棄された後に が消えないことに気付きました。PropertyItemsusingPropertyItemsMemoryStream

Image img2 = null;
using (MemoryStream ms2 = new MemoryStream(imageBytes))
{
    img2 = Image.FromStream(ms2);
    int[] tmp = img2.PropertyIdList;
}
Console.Out.WriteLine("Outside using with PropertyIdList access, Image propertyIDs: ");
foreach (int itemId in img2.PropertyIdList)
    Console.Out.Write(itemId + ", ");
Console.Out.Write("\n");

出力:

Outside using with PropertyIdList access, Image propertyIDs: 
254, 256, 257, 258, 259, 262, 269, 273, 274, 277, 278, 279, 282, 283, 284, 296,

Imageクラスのソースを調べたところ、プロパティがデータのローカル コピーを保持PropertyIdListしていないように見えます。PropertyItemsPropertyItemsMemoryStream

4

2 に答える 2

8

一般に、MemoryStream を破棄することは、かなり役に立たないことです。それ自体には使い捨てのリソースはありません。それは単なるメモリであり、ガベージ コレクターによって既に管理されています。BeginRead/Write() メソッドを使用したことがあり、それらがまだ完了していない場合にのみ問題になります。これは決して行うことではありません。

ただし、CanRead() プロパティを false に設定します。これは、MemoryStream から読み込んだ Bitmap オブジェクトにとって非常に致命的です。

ビットマップを使い続けると、次に何が起こるかはかなり予測不可能です。GDI+ では、ストリームが読み取り可能なままである必要があり、後でそれを使用して、遅延した方法でビットマップ データを読み取ることができます。最も一般的なのは、ビットマップが描画され、「一般的なエラー」でプログラムがかなり確実にクラッシュする傾向がある場合です。

別のコーナーケースを見つけました。これ以上プロパティがないと考えているようです。これはそれほど神秘的ではありません。実際にストリームを閉じたので、読み取ることができるプロパティはこれ以上ありません。そのための例外を生成しないというのは、ずさんですが、GDI+ では珍しいことではありません。

usingステートメントを削除するだけで、何も役に立ちません。とにかくストリームを破棄することに不安がある場合は、Bitmap オブジェクトを使用しなくなった後にそうする必要があります。

于 2013-08-13T17:59:59.437 に答える