- PR -

2つのFormにそれぞれ異なるBitmap画像をそれぞれのタイマで更新表示

投稿者投稿内容
おいたん
会議室デビュー日: 2008/03/10
投稿数: 15
投稿日時: 2008-10-03 21:38
いつも参考にさせていただいております。
表記の件、質問です。

winXP,VC#2005にて開発しています。

2つのFormを作成し、それぞれにpictureBoxを用意。
それぞれ別途準備したBitmap bitmapを、
public void draw()
{
  pictureBox.Image = bitmap;
  Graphics m_grph = Graphics.FromImage(pictureBox.Image);
  ・・・
}
などとしてBitmap画像に追記して、
pictureBoxのPaintイベントで再描画しています。
priavte void pictureBox_Paint(object sender, PaintEventArgs e)
{
  lock(pictureBox.Image)
  {
    e.Graphics.DrawImage(pictureBox.Image,0,0,Width,Height);
  }
}
また、draw関数をスレッドの無限ループ内で呼び出すことで
更新しています。ここはThreading.Timerでもいいです。
子フォームのdraw関数も、子フォーム内で定義されたThreading.Timer
にて呼びだしています。

上記のような描画をそれぞれのFormでさせて両方とも表示しています。
すると、子フォームの描画処理中に以下のようなエラーが
発生してしまいます。

『System.InvalidOperationExceptionのハンドルされていない例外が
 System.Drawing.dllで発生しました。
 
 追加情報:オブジェクトは現在他の場所で使用されています。』

これについて、対策などご教示いただけないでしょうか。
よろしくお願いいたします。
おいたん
会議室デビュー日: 2008/03/10
投稿数: 15
投稿日時: 2008-10-03 21:42
すいません、書き忘れてました。
上記アプリは、MDIにせず、普通のFormを2つ同時に表示させています。
ひょっとしてこれが悪い???

以上、よろしくお願いいたします。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2008-10-03 22:19
Form に表示されるコントロールは、Form が属するスレッドで扱われなければなりません。
おそらく、ブン回されているスレッドと、UI を扱うスレッドの両方から pictureBox にアクセスしようとしているためだと思います。
Invoke のような名前のメソッドがあったと思います。そいつを通してアクセスしてください。
おいたん
会議室デビュー日: 2008/03/10
投稿数: 15
投稿日時: 2008-10-04 01:25
Jittaさん、ご回答いただきありがとうございます。

FormAにpictureBoxAがあり、
FormBにpictureBoxBがあります。

それぞれの画像更新スレッド内で呼び出される
draw関数も、ちゃんとそれぞれdrawA、drawBを
用意しています。drawAでpictureBoxAを更新し、
drawBでpictureBoxBを更新しています。

で、drawAは、FormAで生成されたスレッドにて
呼び出され、drawBは、FormBで生成されたスレッド
にて呼び出されています。

それぞれで表示しているBitmapも、まったく個別に
メモリを割り当てて作成している、異なる画像です。
これでもInvokeメソッドを使用する必要があるのでしょうか?

※ひとつ引っかかるのが、FormBがFormAクラスにて
生成されていることから、FormAがメインスレッドでFormBは
FormAのワーカスレッドになっているのでしょうか?
もしそうなら、drawBを呼び出すためのスレッドは、FormAのメインスレッド
からみると『孫スレッド』みたくなるのでしょうか?
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2008-10-04 09:38
では伺いますが、Form が1つなら、正しく動作するのでしょうか?

正しく動作するなら、私の読み違いです。失礼しました。
おいたん
会議室デビュー日: 2008/03/10
投稿数: 15
投稿日時: 2008-10-04 13:03
はい、Form1つであれば問題なく動作します。

これまでの記載で言いますと、FormAだけを表示
させると、FormA上のpictureBoxAの画像は正しく
更新表示されます。

で、ボタンクリックイベントなどで、FormB.show();
として、FormAクラスが持つFormBを表示させると、
しばらくは両方の画像が正しく更新表示されますが、
不定期にFormB側の画像に手を加えているdrawB関数内の
Graphicsメソッドあたりで前記のエラーが発生している
ような状況です。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2008-10-04 13:45
引用:

おいたんさんの書き込み (2008-10-03 21:38) より:
また、draw関数をスレッドの無限ループ内で呼び出すことで
更新しています。ここはThreading.Timerでもいいです。
子フォームのdraw関数も、子フォーム内で定義されたThreading.Timer
にて呼びだしています。


あまりちゃんと読んではいませんが、雰囲気的には、以前のご投稿の、
件名:スレッドタイマにて一定間隔で呼び出すメソッド内のDLL関数が実行されない
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=45068&forum=7
と同様に、タイマー絡みの問題だろうと推測します。

その時は System.Windows.Forms.Timer を使って解決されたようですが、今回もタイマーの種類をそれと同じにしてもダメなのでしょうか?
今の状況としては、
・それでも解決しない(タイマー以外の問題)
・解決するけど間隔が長いので使いたくない
のいずれなのでしょうか?
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2008-10-05 21:17
引用:

あまりちゃんと読んではいませんが、雰囲気的には、以前のご投稿の、
件名:スレッドタイマにて一定間隔で呼び出すメソッド内のDLL関数が実行されない
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=45068&forum=7
と同様に、タイマー絡みの問題だろうと推測します。


なるほど。前回は UI が絡むスレッドとタイマーの問題で、発生する時と発生しないときがあったわけですね。
今回も、同じ組み合わせのようですね。

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