- PR -

.net2005 C# BackgroundImageをオーバーライドするとOutOfMemoryになってしまいます

投稿者投稿内容
katudon
会議室デビュー日: 2007/04/26
投稿数: 13
投稿日時: 2007-05-13 13:47
囚人さん
ありがとうございます。
また格闘してましたが、やはり解決できませんでした。トレースでは以下のとおりです。
深そうですので、長期になると思います。
解決しましたら、改めて報告したいと思います。
OnPaintの件、ありがとうございます。
貴重なお時間ありがとうございました。


System.OutOfMemoryException はハンドルされませんでした。
Message="メモリが不足しています。"
Source="System.Drawing"
StackTrace:
場所 System.Drawing.TextureBrush..ctor(Image image, WrapMode wrapMode)
場所 System.Windows.Forms.ControlPaint.DrawBackgroundImage(Graphics g, Image backgroundImage, Color backColor, ImageLayout backgroundImageLayout, Rectangle bounds, Rectangle clipRect, Point scrollOffset, RightToLeft rightToLeft)
場所 System.Windows.Forms.Control.PaintBackground(PaintEventArgs e, Rectangle rectangle, Color backColor, Point scrollOffset)
場所 System.Windows.Forms.Control.PaintBackground(PaintEventArgs e, Rectangle rectangle)
場所 System.Windows.Forms.Control.OnPaintBackground(PaintEventArgs pevent)
場所 System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer, Boolean disposeEventArgs)
場所 System.Windows.Forms.Control.WmPaint(Message& m)
場所 System.Windows.Forms.Control.WndProc(Message& m)
場所 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
場所 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
場所 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
場所 System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
場所 System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
場所 System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
場所 System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
場所 System.Windows.Forms.Application.Run(Form mainForm)
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-05-14 07:29
InnerExceptionは空なのかなぁ?

stack overflow ではなく、memory overflow なのが気になる。例外発生時のstack trace は、get アクセッサだけなのでしょうか。
_________________
katudon
会議室デビュー日: 2007/04/26
投稿数: 13
投稿日時: 2007-05-15 10:37
Jittaさん
InnerExceptionはnullです。
ロジックはシンプルに切り出してみたので、getアクセッサのみだと思います。
setアクセッサにもブレークをかけて見ましたがこちらには飛んでないようです。
HashTableを使わないで、通常のImageで内部変数をもち、BackgroundImageをオーバーライドしてこのImageで処理してみるとこのような現象はおこりません。
Apprication.Runで例外でブレークしますので、描画段階での処理で起きているようです。
かつて、Fontをアンビエントプロパティと気づかすにオーバーライドしたときに酷似した現象がおきたので、BackgroundImageもそうなのかと思い調べましたが、アンビエントプロパティではなかったです。。。確かにStack overflowではないですね。
漠然とですが
(1)Collection系がだめなのか。ArrayListにしてみてトライする
(2)ダブルバッファ
あたりから調べてみます。
katudon
会議室デビュー日: 2007/04/26
投稿数: 13
投稿日時: 2007-05-15 13:01
Jitta様、囚人様
すみません。解決いたしました。
ちなみにHashTableが問題ではなく、単純に内部変数でImageの変数をとって表示させようとしても現象が発生していました。先ほどの報告に間違いがありました。申し訳ありません。



検索中に以下の記事を見ていて気づきました。
http://www.atmarkit.co.jp/fdotnet/dotnettips/194nopaintbg/nopaintbg.html
OutOfMemoryについては、解せないありますが、OnPaintの前にOnPaintBackgroundが呼ばれているのは確かのようで

カスタムコントロールに
protected override void OnPaintBackground(PaintEventArgs pevent)
{
// 何もしない
// base.OnPaintBackground(pevent);
}
を追加することで、OutOfMemoryの現象は回避されています。
この記事以前に読んでいたのですが、見落としていました。

色々指針をいただき解決することができました。
ありがとうございます。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-05-16 06:22
 Bitmap のコンストラクタを、Stream を渡すもの以外に変えても解決するような気もする。
何となく、参照じゃなくてディープ コピーになっているように思う。
理由は、stream を確保し続けるところ。
stream が参照コピーできず、byte 配列にコピーし直してイメージを作り直しているんじゃないかなぁ?なもんだから、OutOfMemory になる、と。
繰り返すけど、気がするだけ。

ちげー。スタックに出てないやん。
失礼しました。


 囚人さんの、再現できなかったというコードを公開して欲しいところ。おそらく、イメージは取り込んでしまってから Bitmap を作るようにコーディングしてあると思う。



[ メッセージ編集済み 編集者: Jitta 編集日時 2007-05-16 06:52 ]

スキルアップ/キャリアアップ(JOB@IT)