別スレッドから、一定時間毎にフォーム上に配置したTImageの内容を
書き換える処理を行っているのですが、たまに、EOutOfResourcesエラーが発生します。
TImageのハンドルが取得できなくなっているのではないか、と思うのですが、
どのように対処すればいいのかわかりません。
・別スレッドで行っているのは、下記のような内容です。
Graphics::TBitmap bmpBuffer;
//---------------------------------------------------------------------------
void __fastcall thread_proc::Execute()
{
bmpBuffer = new Graphics::TBitmap();
bmpBuffer->HandleType = bmDIB;
bmpBuffer->PixelFormat = pf1bit;
bmpBuffer->SetSize(100, 300);
while(true) {
// bmpBuffer->Canvasを使用した描画処理
Synchronize(&ImgUpdate);
i++;
Sleep(100);
}
delete bmpBuffer;
}
//---------------------------------------------------------------------------
void __fastcall thread_proc::ImgUpdate()
{
Form1->ImgPrev->Picture->Bitmap->Assign(bmpBuffer);
}
わかる方がいらっしゃいましたら、ご教授いただければと思います。
よろしくお願いします。
ソースから判断すると、左下に動いていくようなアニメーションを表示したいのですか?
元の描画がどのように行っているのかわからないですが、
CopyRectを呼び出すインスタンスと、CopyRectの第2引数のインスタンスが同一でもいいのでしょうか?
これがAPIでサポートされているかは分かりますか?
これで解決するかどうかも分かりませんが、オリジナルの絵を持ったTBitmapオブジェクトを作成しておいて、この処理を通るたびに、SrcRectの値と、DstRectの値を変えて、そのオリジナルのTBitmapのTCanvasから、上記のソース中のbmpBufferのTBitmapの持つTCanvasにコピーするようにしたらどうでしょうか?
全体が見えないので、原因も明確に見えないので、はずしている可能性は大ですが。
回答ありがとうございます。
try/catchを使って、例外が発生する箇所の特定を試みたところ、
// bmpBuffer->Canvasを使用した描画処理
部分で行っているCopyRectにて、EOutOfResources例外が発生しているようでした。
//該当部分のソース
TRect SrcRect, DstRect;
SrcRect = Rect(0, 0, 100, 300 - 8);
DstRect = Rect(0, 8, 100, 300);
try {
bmpBuffer->Canvas->CopyRect(DstRect, bmpBuffer->Canvas, SrcRect);
} catch (EOutOfResources &e) {
ShowMessage("EOutOfResources at CopyRect");
}
なぜ、このようになるのかわからないのですが、引き続き調査したいと思います。
Borland提供のAPIは詳しくないので、はずしていたら申し訳ないですが、
あやしいところをtry/catchで囲めばいいのでは?
try {
bmpBuffer = new Graphics::TBitmap();
} catch (EOutOfResources e) {
//エラーメッセージ
}
これで、エラーメッセージがでれば、TBitmapのコンストラクタが例外を投げていると分かるでしょう。
明らかにあやしい処理があれば、こんな感じでピンポイントでチェックして、それで見つからなければ、try/catchの範囲を色々変えてみればいかがですか?
何かの参考になれば。
知識不足でEOutOfResources例外が投げられる場所を特定する方法がわかりませんでした。。。
いただいた内容(推測ではなく原因を調査する必要があるという点)はごもっともだと思いますので、
何とか例外がおきている箇所を特定する方法を模索したいと思います。
ご回答いただき、ありがとうございました!
いただいた方法を元に、全GDI数を計算した所、2000強でした。
また、作成したアプリケーションのみのGDI数は55程度で、GDI数に引っかかっているようではありませんでした。
引き続き、原因を調査したいと思います。
ご回答いただき、ありがとうございました!
C++ Builder は使ったことはありませんが、以下が原因ではないでしょうか?
Windows の仕様で「プロセス毎の GDI オブジェクト数」の制限(Windows 2000/XP の既定値:10,000個)というのがあります。
通常、使用した GDI オブジェクトを正しく開放していれば、問題ありませんが、取得して開放しなかったりすると、だんだんリークしていって、リソースが足りなくなります。
GDI オブジェクト数は、タスクマネージャで確認することができます。
該当プロセスの GDI オブジェクト数が 9,999 個に達していないか確認してみてください。
<GDI オブジェクト数の確認方法> 1. [Ctrl] + [Shift] + [ESC] にて「タスクマネージャ」を起動します。 2. [表示] - [列の選択] メニューを選択します。 3. 「列の選択」ダイアログにて [GDI オブジェクト] にチェックを入れ [OK] ボタンを押下します。
<参考情報> ■ Windows XP または Windows 2000 でプロセスが GDI オブジェクト クォータを超えた場合、 デスクトップのアプリケーション メニューが正しく表示されない http://support.microsoft.com/kb/838283/ja ■ はてブ閲覧時のリソース不足 http://q.hatena.ne.jp/1227957618
まずは、EOutOfResourcesの例外が投げられる場所を特定してはどうですか?
対処法の前に、原因を確定させないと難しいでしょう。