そんなに馬鹿げたことではありません。経験則として、JPEGは、平均して、BMPとして保存された同じ画像のサイズの約10%であることに注意してください。圧縮率の高い画像と圧縮率の低い画像があり、JPEGエンコーダーの品質と圧縮設定によって大きな違いが生じますが、私の経験では、この信条は通常当てはまります。
この場合、ルールをtrueとして受け入れると、プログラムは少なくとも720MBの画像データのみを保存します。バイト配列とMemoryStreamsに60MBのJPEGデータがあり、次に600MBの非圧縮BMP画像があります。さらに、プログラムはそれ自体と参照されているサードパーティのバイナリを同じメモリスペースにロードします(参照されているFramework名前空間のDLLを含む。フレームワークが「組み込み」であるという理由だけで「自由に」使用できるわけではないことを忘れがちです。 )、そして特定のコレクションは非常に楽観的な方法で自分自身のメモリを要求することを覚えておいてください。たとえば、リストの内部最大容量に達するたびに、リストは以前のサイズの2倍にサイズ変更されます。辞書も同じように機能しますが、2つの内部配列構造を維持するためのオーバーヘッドが追加されます。キーハッシュ用に1つ、もう1つは、キーハッシュにリンクされている実際の値を含む「ノード」用です。この動作により、多数のオブジェクトのコレクションを処理するプログラムが、ランタイムが提供できるよりも多くのメモリを要求する可能性が非常に高くなります。次に、これがグラフィカルアプリケーションの場合、ランタイムはグラフィカル要素を処理する各スレッドのメッセージループを維持し、すべてのグラフィカル要素(各「ウィンドウ」にフックします。ただし、この用語は事実上すべてのGUI要素が「ウィンドウ」、通常ウィンドウと呼ぶフォームオブジェクトだけではありません)。
これらすべてにより、アプリケーションに1.6GBのマネージドメモリを簡単に要求させることができます。次に、アプリケーションが400MB以上のメモリ(大規模なコレクションのサイズを変更するため)または21億を超える新しいハンドルを要求すると(.NETは64ビットOSでも32ビットインデックスを使用するため、ランタイムはプロセスごとに合計232の異なるメモリアドレスを追跡します)、ランタイムはOOMEを挿入します。