4

私のコンパクトフレームワークアプリケーションは、すべてのアイテムを大きなビットマップサーフェスにレンダリングし、そのビットマップを画面上のオフセット位置にコピーして、適切なアイテムのみが表示されるようにすることで、スムーズなスクロールリストを作成します。古いバージョンでは、その時点で画面に表示されるはずのアイテムしかレンダリングされませんでしたが、このアプローチは、スムーズなスクロールインターフェイスには遅すぎました。

大きなビットマップを最初に作成するときに、OutOfMemoryExceptionが生成されることがあります。ユーザーがデバイスのソフトリセットを実行してアプリケーションを再実行すると、問題なく作成を実行できます。

アプリケーションは新しいスムーズスクロールメソッドの前とほぼ同じ量のプログラムメモリを使用するため、このビットマップがプログラムメモリで生成されているようには見えません。

この例外を防ぐ方法はありますか?例外がスローされる前に(どこにいても)必要なメモリを解放する方法はありますか?

4

4 に答える 4

1

そして、投稿するとすぐに、新しいバージョンの問題を解決するためにできることを考えました。あなたが抱えている問題は、CFが巨大なビットマップに使用可能な連続したメモリの1つのブロックを見つけようとしていることであり、これは時々問題になります。

1つの大きなビットマップを作成する代わりに、アイテムごとに1つずつ、小さなビットマップのコレクションを作成し、各アイテムを独自の小さなビットマップにレンダリングできます。表示中に、必要なビットマップをコピーするだけです。CFは、1つの大きなビットマップよりも小さなビットマップの束を作成する方がはるかに簡単であり、これが本当に膨大なアイテムの束でない限り、メモリの問題は発生しないはずです。

「修正はありません」のような表現は避けるべきです。

もう1つの重要なポイント:終了したら、各ビットマップでDispose()を呼び出すようにしてください。

于 2008-11-18T03:25:41.967 に答える
1

完全にレンダリングされたデータのサイズが明らかに問題になるため、データの一部のみをレンダリングする古いメカニズムに戻ることをお勧めします。レンダリングの問題を防ぐために、おそらく現在のビューの上下に数行を事前レンダリングして、影響を抑えて「スクロール」できるようにします。

于 2008-11-18T15:16:13.967 に答える
0

あなたのビットマップ間違いなくプログラムメモリに作成されています。ビットマップに必要なメモリの量は、ビットマップの大きさによって異なります。また、この必要なサイズでOutOfMemoryExceptionが生成されるかどうかは、PDAで使用できる量によって異なります(これにより、ランダムに発生するエラーが発生します)。

申し訳ありませんが、これは一般的に(特にCompact Frameworkでは)お勧めできないコントロールレンダリング手法であり、PDAの物理メモリを増やす以外に修正はありません。これは通常は不可能です(そして、とにかく問題を修正しないことがよくあります)。 、CFプロセスは、デバイスがどれだけ使用可能であっても32MBに制限されているため)。

最善の策は、古いバージョンに戻ってレンダリング速度を向上させることです。ちらつきをなくすためにコントロールをダブルバッファリングするためのCFで利用可能な簡単なテクニックもあります。

于 2008-11-18T03:20:05.160 に答える
0

作成できるビットマップ スペースの合計サイズを制限するデバイス制限に遭遇したように見えるので (これらは一般的なプログラム メモリではなくビデオ RAM で作成されるようです)、ここで使用されている大きな Bitmap オブジェクトをBitBlt API 関数を PInvoking することにより、読み取りと書き込みのためにアクセスする Windows メモリのプレーンな古いブロック。

最初にメモリブロックを作成するのは難しいので、おそらくそれについて別の SO の質問をしたいでしょう (GCHandle.Alloc をここで使用して、「固定された」オブジェクトを作成できます。つまり、.NET はそれを移動することができません)ここで重要なメモリ)。私はそれを行う方法を知っていますが、それを正しく行うかどうか確信が持てず、むしろ専門家の意見が欲しいです.

大きなブロックを作成したら、アイテムを反復処理し、それぞれを (既存の .NET コードを使用して) 再利用し続ける 1 つの小さなビットマップにレンダリングし、それをメモリ ブロックの適切な場所に BitBlt します。

キャッシュ全体を作成した後、レンダリング コードは以前と同じように機能するはずですが、大きなビットマップからレンダリング サーフェスにコピーする代わりに、キャッシュ ブロックから BitBlt を実行するという違いがあります。BitBlt の引数は基本的に DrawImage と同じです (宛先、ソース、座標、サイズなど)。

専用のビデオ RAM ではなく、この方法で通常のメモリからキャッシュを作成しているため、同じ問題に遭遇することはないと思います。ただし、ブロック作成コードを最初に動作させ、毎回十分な大きさのブロックを作成できることを確認するためにテストします。

更新: 実際には、理想的なアプローチは、1 つの大きなメモリ ブロックではなく、小さなメモリ ブロックのコレクションを持つことです (ビットマップ アプローチの問題だと思っていたように)。私は 5 MB および 10 MB のオブジェクトを処理する CF アプリを使用してきましたが、とにかく大きな問題ではありません (ただし、そのチャンクが固定されている場合はより大きな問題になる可能性がありますが、わかりません)。ところで、ビットマップが利用可能なメモリよりもはるかに小さいことを知っていたので、ビットマップ作成の OOME にはいつも驚かされていました。その理由がわかりました。申し訳ありませんが、これは最初は簡単な解決策だと思っていました。

于 2008-11-18T15:12:16.953 に答える