C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[21]: C#タイマーでのpictureBox.Image更新nitu


(過去ログ 51 を表示中)

[トピック内 29 記事 (1 - 20 表示)]  << 0 | 1 >>

■27520 / inTopicNo.1)  C#タイマーでのpictureBox.Image更新nitu
  
□投稿者/ フミ (1回)-(2008/11/08(Sat) 20:15:51)

分類:[.NET 全般] 

はじめまして。
フミと申します。


VC#2008でピクチャーボックス内の絵を更新するプログラムを作成しています。
タイマーで10msでイベントをおこし、
ピクチャーボックスへ512×512のBitmapを入れ替える
プログラムをつくったのですが、エラーが発生します。
たぶん、早すぎておいつかないのだと思われるのですが、
エラーの内容がよくわかりません。
どなたか詳しくわかる方がいらっしゃればご教授ください。
よろしくお願いいたします。



下記がそのプログラムとエラー内容です。
Resources.aaaaaとResources.bbbbbはそれぞれ512×512のビットマップです。

using System.Windows.Forms;
using System;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private System.Timers.Timer timeTimer;

private void timeTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
setPicture();
}

public Form1()
{
InitializeComponent();

timeTimer = new System.Timers.Timer(10);
timeTimer.Elapsed += new System.Timers.ElapsedEventHandler(timeTimer_Elapsed);
timeTimer.Start();
}

private void setPicture()
{
pictureBox1.Image = Properties.Resources.aaaaa;
pictureBox1.Image = Properties.Resources.bbbbb;
}
}
}


***エラー内容

System.InvalidOperationException: オブジェクトは現在他の場所で使用されています。
場所 System.Drawing.Image.get_FrameDimensionsList()
場所 System.Drawing.ImageAnimator.CanAnimate(Image image)
場所 System.Drawing.ImageAnimator.ImageInfo..ctor(Image image)
場所 System.Drawing.ImageAnimator.Animate(Image image, EventHandler onFrameChangedHandler)
場所 System.Windows.Forms.PictureBox.Animate(Boolean animate)
場所 System.Windows.Forms.PictureBox.Animate()
場所 System.Windows.Forms.PictureBox.InstallNewImage(Image value, ImageInstallationType installationType)
場所 System.Windows.Forms.PictureBox.set_Image(Image value)
場所 WindowsFormsApplication1.Form1.setPicture() 場所 D:\dotNET_program\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs:行 67
引用返信 編集キー/
■27521 / inTopicNo.2)  Re[1]: C#タイマーでのpictureBox.Image更新nitu
□投稿者/ 倉田 有大 (330回)-(2008/11/08(Sat) 20:34:25)
No27520 (フミ さん) に返信
> はじめまして。
> フミと申します。
>
>
> VC#2008でピクチャーボックス内の絵を更新するプログラムを作成しています。
> タイマーで10msでイベントをおこし、
> ピクチャーボックスへ512×512のBitmapを入れ替える
> プログラムをつくったのですが、エラーが発生します。
> たぶん、早すぎておいつかないのだと思われるのですが、
> エラーの内容がよくわかりません。
> どなたか詳しくわかる方がいらっしゃればご教授ください。
> よろしくお願いいたします。

10msはちょっと無謀ですね。

>System.InvalidOperationException: オブジェクトは現在他の場所で使用されています。

書いてあるとおりに、なんかのオブジェクトの使用がおわっていないのに、またオブジェクトを使用したからです。
これじゃsetPictureが何重にもよばれてしまいます。

lock(this)
{
setPicture();
}

lockで囲ってやるのが一つの手ですけど、できたらsetPicture内でフラグをたてて、setPictureの処理が終わる前に、setPictureがよばれない処理を
追加した方がよいとおもいます。

引用返信 編集キー/
■27524 / inTopicNo.3)  Re[2]: C#タイマーでのpictureBox.Image更新nitu
□投稿者/ 倉田 有大 (331回)-(2008/11/08(Sat) 22:39:03)
忘れてた。
フォームはフォームを生成したスレッドでしかあつかっちゃだめです。
Invokeで、フォームを生成したスレッドでsetPictureの処理をしてください。

http://www.atmarkit.co.jp/fdotnet/dotnettips/312ctrlinvoke/ctrlinvoke.html
引用返信 編集キー/
■27534 / inTopicNo.4)  Re[1]: C#タイマーでのpictureBox.Image更新nitu
□投稿者/ Jitta on the way (215回)-(2008/11/09(Sun) 10:34:23)
No27520 (フミ さん) に返信
> はじめまして。
> フミと申します。
>
>
> VC#2008でピクチャーボックス内の絵を更新するプログラムを作成しています。
> タイマーで10msでイベントをおこし、

10ms に一回ということは、1秒、つまり 1000ms の間に 100回、差し替えることを意味します。
人の目は、そんなに精度がよくありません。アニメーションでさえ 25回程度です。

というわけで、System.Windows.Forms.Timer が使えます。こちらなら、GUI スレッドでイベントが発生するので、Invoke する必要がありません。
引用返信 編集キー/
■27548 / inTopicNo.5)  Re[2]: C#タイマーでのpictureBox.Image更新nitu
□投稿者/ 倉田 有大 (333回)-(2008/11/09(Sun) 15:55:18)
> というわけで、System.Windows.Forms.Timer が使えます。こちらなら、GUI スレッドでイベントが発生するので、Invoke する必要がありません。

こっちも、msで設定できたのか−!
sの設定と勘違いしてました。
引用返信 編集キー/
■27562 / inTopicNo.6)  Re[3]: C#タイマーでのpictureBox.Image更新nitu
□投稿者/ フミ (3回)-(2008/11/10(Mon) 10:00:09)
>倉田様、Jitta on the way様

ご回答ありがとうございます!
やはりこの速度では無謀ですよね。。
とりあえず、教えていただいた方法で、
速度をおとして試してみます。


ただ不思議なのは
上記のプログラムにて

private readonly object lockObject = new object

というフィールドをつけくわえて、
タイマーから呼び出される関数内で

lock(lockObject)
{
setPicture();
}

としたのですが、
やはり

>>>>System.InvalidOperationException: オブジェクトは現在他の場所で使用されています。

とエラーが表示されたことです。
Lockをした場合には、
他のスレッドは処理が終わるまでブロックされて待ってくれると思っていたのですが。。。
Lockの書き方が誤っていたのでしょうか。。
引用返信 編集キー/
■27572 / inTopicNo.7)  Re[4]: C#タイマーでのpictureBox.Image更新nitu
□投稿者/ Jitta on the way (218回)-(2008/11/10(Mon) 12:49:24)
No27562 (フミ さん) に返信
> Lockの書き方が誤っていたのでしょうか。。

いえ、lock をしても無駄です。GUI スレッドで処理をしなければかなりません。

Forms.Timer は、GUI スレッドでイベントが発生します。
引用返信 編集キー/
■27586 / inTopicNo.8)  Re[5]: C#タイマーでのpictureBox.Image更新nitu
□投稿者/ 倉田 有大 (336回)-(2008/11/10(Mon) 17:41:56)
>他のスレッドは処理が終わるまでブロックされて待ってくれると思っていたのですが。。。

pictureBoxはその関数内だけじゃなく、フォームを作ったスレッドでも使われているからじゃないかな(憶測
私のlockの例は、以前、画像処理をしたとき、susiepluginがマルチスレッドに対応していなくてlockを使用したからでした、すいません。
引用返信 編集キー/
■27589 / inTopicNo.9)  Re[6]: C#タイマーでのpictureBox.Image更新nitu
□投稿者/ Jitta on the way (219回)-(2008/11/10(Mon) 20:14:38)
No27586 (倉田 有大 さん) に返信
> >他のスレッドは処理が終わるまでブロックされて待ってくれると思っていたのですが。。。
>
> pictureBoxはその関数内だけじゃなく、フォームを作ったスレッドでも使われているからじゃないかな(憶測

「他のスレッドは待つはずだから、同時に使用することにはならないのでは?」ってことですよ。


それは違います。待つのは lock をしようとして、主導権を取れなかったときです。従って、lock しようとしないスレッドを、待たせることは出来ません。なので、GUI スレッドに処理をさせて下さい。
引用返信 編集キー/
■27657 / inTopicNo.10)  Re[7]: C#タイマーでのpictureBox.Image更新nitu
□投稿者/ フミ (4回)-(2008/11/11(Tue) 21:09:08)
2008/11/11(Tue) 21:11:47 編集(投稿者)

倉田様、Jitta on the way様

ご返信ありがとうございます。
タイマーに関しては、
ご助言のようにして確認中です。

実は1つ試したことがあります。
以下のようなプログラムを試しました。
ボタンを押すと
スレッド上で1つのピクチャーボックスに
何度もBmp(512×512)の絵を入れ替えるというものだけのものです。
これだけで、
全く同じエラー
>System.InvalidOperationException: オブジェクトは現在他の場所で使用されています。
がでてしまいます。
ただ1つのスレッドだけでも、スレッドを用いると
中の処理(setPicture)は上から順番に処理されるのではなく、
細切れに実行されてしまうのですか??
すいません、初心者なのでここのところがよくわかりません。。。
pictureBox1に絵を入れる操作が同時に行われてしまうせいで、
オブジェクトは他の場所で使われているというエラーがでるということですよね??

以下のプログラムだとエラーがでますが、
t.start()の後に、
t.join()で
待ってあげると
エラーはでませんでした。
やはりブロックとかが関係しているのでしょうか。
だからGUIスレッドにwindows.Form.timerをおいて処理をさせればよいということですか。


以下プログラム

using System.Windows.Forms;
using System;
using System.Threading;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void setPicture()
{
for (int i = 0; i < 20000; i++)
{
pictureBox1.Image = Properties.Resources.aaaaa;
pictureBox1.Image = Properties.Resources.bbbbb;
pictureBox1.Image = Properties.Resources.aaaaa;
pictureBox1.Image = Properties.Resources.bbbbb;
pictureBox1.Image = Properties.Resources.aaaaa;
pictureBox1.Image = Properties.Resources.bbbbb;
pictureBox1.Image = Properties.Resources.aaaaa;
pictureBox1.Image = Properties.Resources.bbbbb;
}
}

private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(setPicture));
t.Start();
}
}
}
引用返信 編集キー/
■27663 / inTopicNo.11)  Re[8]: C#タイマーでのpictureBox.Image更新nitu
□投稿者/ Jitta (534回)-(2008/11/11(Tue) 22:33:47)
Jitta さんの Web サイト
No27657 (フミ さん) に返信

> ただ1つのスレッドだけでも、スレッドを用いると
> 中の処理(setPicture)は上から順番に処理されるのではなく、
> 細切れに実行されてしまうのですか??
> すいません、初心者なのでここのところがよくわかりません。。。
> pictureBox1に絵を入れる操作が同時に行われてしまうせいで、
> オブジェクトは他の場所で使われているというエラーがでるということですよね??

まず、製品に付属しているドキュメントに当たりましょう。
http://msdn.microsoft.com/ja-jp/library/ms171728.aspx

これは、System.Windows.Forms.Form の親である、System.Windows.Forms.Control の説明の中にリンクがあります。

 開発者が1つのつもりでも、実際にはもう少し多くのスレッドができています。そして、System.Windows.Forms.Control を継承するコントロールを描画することについては、コントロールの作成元スレッドが行わなければなりません。

 なお、以前の私の投稿で「GUI スレッド」としているのは、「コントロールの作成元スレッド」のことです。「コントロールの作成元スレッド」は1つだと思っていたのですが、複数のスレッドで別々のコントロールを作成することができそうです。
引用返信 編集キー/
■27697 / inTopicNo.12)  Re[9]: C#タイマーでのpictureBox.Image更新nitu
□投稿者/ フミ (5回)-(2008/11/12(Wed) 15:53:28)
No27663(Jitta様)に返信

ご助言ありがとうございます!
教えていただいた
http://msdn.microsoft.com/ja-jp/library/ms171728.aspx
を参考にして■No27657のプログラムは
エラー(>System.InvalidOperationException: オブジェクトは現在他の場所で使用されています。)
がでなくなりました。
下記のように修正しました。
ピクチャーボックスにデリゲートを通じて絵をわたしました。

あと最初の質問時のタイマーのやつですが、
windows.forms.timerだと処理中に操作ができなくなってしまいました。
無謀な時間での大きいサイズの絵の更新の問題は置いておくとして、
タイマーイベントで描画中にも画面にあるボタンを押したりするには、
windows.forms.timerだとダメですか??




以下プログラム

using System.Windows.Forms;
using System;
using System.Threading;
using System.Drawing;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
//画面表示用デリゲート
public delegate void SetImageCallback(Bitmap inBmp);

public Form1()
{
InitializeComponent();
}
private void setPicture()
{
for (int i = 0; i < 20000; i++)
{
//pictureBox1.Image = Properties.Resources.aaaaa;
//pictureBox1.Image = Properties.Resources.bbbbb;
//pictureBox1.Image = Properties.Resources.aaaaa;
//pictureBox1.Image = Properties.Resources.bbbbb;
//pictureBox1.Image = Properties.Resources.aaaaa;
//pictureBox1.Image = Properties.Resources.bbbbb;
//pictureBox1.Image = Properties.Resources.aaaaa;
//pictureBox1.Image = Properties.Resources.bbbbb;
//
// ↓下記に変更
//

SetBmp(Properties.Resources.aaaaa);
SetBmp(Properties.Resources.bbbbb);
SetBmp(Properties.Resources.aaaaa);
SetBmp(Properties.Resources.bbbbb);
SetBmp(Properties.Resources.aaaaa);
SetBmp(Properties.Resources.bbbbb);
SetBmp(Properties.Resources.aaaaa);
SetBmp(Properties.Resources.bbbbb);

}
}

private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(setPicture));
t.Start();
}

//画面表示用デリゲート
private void SetBmp(Bitmap inBmp)
{
if (this.pictureBox1.InvokeRequired)
{
SetImageCallback d = new SetImageCallback(SetBmp);
this.Invoke(d, new object[] { inBmp });
}
else
{
this.pictureBox1.Image = inBmp;
}
}
}
}

引用返信 編集キー/
■27701 / inTopicNo.13)  Re[10]: C#タイマーでのpictureBox.Image更新nitu
□投稿者/ 倉田 有大 (337回)-(2008/11/12(Wed) 16:56:24)
No27697 (フミ さん) に返信
> ■No27663(Jitta様)に返信
>
> ご助言ありがとうございます!
> 教えていただいた
> http://msdn.microsoft.com/ja-jp/library/ms171728.aspx
> を参考にして■No27657のプログラムは
> エラー(>System.InvalidOperationException: オブジェクトは現在他の場所で使用されています。)
> がでなくなりました。
> 下記のように修正しました。
> ピクチャーボックスにデリゲートを通じて絵をわたしました。
>
> あと最初の質問時のタイマーのやつですが、
> windows.forms.timerだと処理中に操作ができなくなってしまいました。
> 無謀な時間での大きいサイズの絵の更新の問題は置いておくとして、
> タイマーイベントで描画中にも画面にあるボタンを押したりするには、
> windows.forms.timerだとダメですか??

timerの処理中というより、Invokeでオーナー スレッド(フォームを作成したスレッド)に処理が渡っています。
setPicture関数抜けないと、画面の操作ができないですよ。
普通は、setPictureの処理を軽くするように作るんじゃないかな。
この場合、DoEvents使うとどうなるだろう?

別スレッドでコントロールを作成して、そのスレッドでコントロールする手はあるのかな(他のスレでも話題になってますが)
その場合は、フォームにそのコントロールはりつけられるのだろうか?^^;もうわからん

#ちょw おーなーすれっどとカタカナでかこうとしたら、なーす(カタカナ)は投稿出ませんと出たw
引用返信 編集キー/
■27702 / inTopicNo.14)  Re[10]: C#タイマーでのpictureBox.Image更新nitu
□投稿者/ フミ (6回)-(2008/11/12(Wed) 16:59:14)
最初の質問(■No27520)のプログラムの修正

以下のようにプログラムを修正しましたら、
タイマーで無謀なサイズ・無謀な時間で画像更新を行っても、
エラー(>System.InvalidOperationException: オブジェクトは現在他の場所で使用されています。)
はでなくなりました。
timerはwindows.forms.timerだとフォーム自体を動かせなくなってしまったので、
やはり最初と同じsystem.timers.timerを使いました。
またイベントに再入してもよいように防御しました。
(interLockを用いました。たぶんこれで大丈夫?なのか???)
しかし、タイマーをストップするときやフォームを×印で閉じると
以下のエラーがでます。。。

「破棄されたオブジェクトにアクセスできません。
 オブジェクト名 'Form1' です。」

タイマーを破棄したときに
イベントが無視されsetPicture()を実行しないようにしないとまずそうです。。。

???ここのコメントに書くとプログラムのTabが消滅してみにくくなってしまいますね。。。
???どうにかなるのでしょうか??

以下修正版プログラム

using System;
using System.Windows.Forms;
using System.Threading;
using System.Drawing;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
//画面表示用デリゲート
private delegate void SetImageCallback(Bitmap inBmp);

//画面更新用タイマー
private System.Timers.Timer timeTimer;

//再入防御用フラグ
private int syncPoint = 0;

//メインフォーム
public Form1()
{
//コンポーネントの初期化
InitializeComponent();

//タイマーの生成
timeTimer = new System.Timers.Timer(10);
timeTimer.Elapsed += new System.Timers.ElapsedEventHandler(timeTimer_Elapsed);
timeTimer.Enabled = true;
}

//タイマーのイベント
void timeTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
//再入の防止
if (Interlocked.CompareExchange(ref syncPoint, 1, 0) == 0)
{
//絵の更新
setPicture();
syncPoint = 0;
}
else
{
//何もしない
}

}

//絵の更新用メソッド
private void setPicture()
{
SetBmp(Properties.Resources.aaaaa);//絵1
SetBmp(Properties.Resources.bbbbb);//絵2
}

//画面表示用デリゲート
private void SetBmp(Bitmap inBmp)
{
if (this.pictureBox1.InvokeRequired)
{
SetImageCallback d = new SetImageCallback(SetBmp);
this.Invoke(d, new object[] { inBmp });
}
else
{
this.pictureBox1.Image = inBmp;
}
}
}
}

引用返信 編集キー/
■27703 / inTopicNo.15)  Re[11]: C#タイマーでのpictureBox.Image更新nitu
□投稿者/ フミ (7回)-(2008/11/12(Wed) 17:09:13)
2008/11/12(Wed) 17:11:14 編集(投稿者)

No27701(倉田様)へ返信

>timerの処理中というより、Invokeでオーナー スレッド(フォームを作成したスレッド)に処理が渡っています。
>setPicture関数抜けないと、画面の操作ができないですよ。

デリゲートの書き方まずかったですか??
this.Invoke(d, new object[] { inBmp });
の部分ですか??
MSDNのコピーでTextの部分をpictureBoxに変更しただけなのです。
スレッドセーフなコントロールの使い方のところなのですが。。
(⇒http://msdn.microsoft.com/ja-jp/library/ms171728.aspx)ここのやつです。。。
ただ、上記プログラムで画面の操作(フォームの移動やボタンを押すなど)は何故かできています。
setPicture()が早く終了するからでしょうか。。。
引用返信 編集キー/
■27704 / inTopicNo.16)  Re[11]: C#タイマーでのpictureBox.Image更新nitu
□投稿者/ 倉田 有大 (338回)-(2008/11/12(Wed) 17:14:27)
2008/11/12(Wed) 17:46:58 編集(投稿者)
2008/11/12(Wed) 17:28:39 編集(投稿者)

>>timerの処理中というより、Invokeでオーナー スレッド(フォームを作成したスレッド)に処理が渡っています。
>>setPicture関数抜けないと、画面の操作ができないですよ。
>デリゲートの書き方まずかったですか??

失礼、setPictureの中でInvoke呼びまくっているんですね。
これは、どうなってるのかな^^;
わからないので、無視してください。

「破棄されたオブジェクトにアクセスできません。
 オブジェクト名 'Form1' です。」

>タイマーを破棄したときに
>イベントが無視されsetPicture()を実行しないようにしないとまずそうです。。。

私も昔やりました。
タイマーを止めて、DoEventsつかったり、いろいろやったような。
今組むとどうやるかな。

>???ここのコメントに書くとプログラムのTabが消滅してみにくくなってしまいますね。。。
>???どうにかなるのでしょうか??

図表モードをクリックでどうですか?

>timeTimer = new System.Timers.Timer(10);
>timeTimer.Elapsed += new System.Timers.ElapsedEventHandler(timeTimer_Elapsed);
>timeTimer.Enabled = true;

>private void SetBmp(Bitmap inBmp)
>{
>if (this.pictureBox1.InvokeRequired)
>{

すごい勢いで、メッセージポンプにメッセージがたまっていきそうなんですが、大丈夫なのかな?
って、Interlockedで制御しているのかな。失礼。

引用返信 編集キー/
■27721 / inTopicNo.17)  Re[11]: C#タイマーでのpictureBox.Image更新nitu
□投稿者/ Jitta (537回)-(2008/11/12(Wed) 21:57:07)
Jitta さんの Web サイト
No27702 (フミ さん) に返信
> 最初の質問(■No27520)のプログラムの修正
> 
> 
> 
> 以下修正版プログラム
> 
> using System;
> using System.Windows.Forms;
> using System.Threading;
> using System.Drawing;
> 
> namespace WindowsFormsApplication1
> {
>     public partial class Form1 : Form
>     {
>         //画面表示用デリゲート
>         private delegate void SetImageCallback(Bitmap inBmp);
> 
>         //画面更新用タイマー
>         private System.Timers.Timer timeTimer;
> 
>         //再入防御用フラグ
>         private int syncPoint = 0;
> 
>         //メインフォーム
>         public Form1()
>         {
>             //コンポーネントの初期化
>             InitializeComponent();
> 
>             //タイマーの生成
>             timeTimer = new System.Timers.Timer(10);
>             timeTimer.Elapsed += new System.Timers.ElapsedEventHandler(timeTimer_Elapsed);
>             timeTimer.Enabled = true;
>         }
> 
>         //タイマーのイベント
>         void timeTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
>         {
>             //再入の防止
>             if (Interlocked.CompareExchange(ref syncPoint, 1, 0) == 0)
>             {
>                 //絵の更新
>                 setPicture();
>                 syncPoint = 0;
>             }
>             else
>             {
>                 //何もしない
>             }
> 
>         }
> 
>         //絵の更新用メソッド
>         private void setPicture()
>         {
>             SetBmp(Properties.Resources.aaaaa);//絵1
>             SetBmp(Properties.Resources.bbbbb);//絵2
>         }

ここで2つの絵を差し替えていますが、aaaaa の方は、表示されますか?
それとも、bbbbb の読み込みに時間がかかるので、その間は表示されているのでしょうか?
setPicture に入ってきた回数で、aaaaa と bbbbb を入れ替えればいいのでは?
また、2つしかないのなら、PictureBox を2つ用意し、表示/非表示を切り替えるようにすれば、もっと高速に表示できますよね?
> 
>         //画面表示用デリゲート
>         private void SetBmp(Bitmap inBmp)
>         {
>             if (this.pictureBox1.InvokeRequired)
>             {
>                 SetImageCallback d = new SetImageCallback(SetBmp);
>                 this.Invoke(d, new object[] { inBmp });
>             }
>             else
>             {
>                 this.pictureBox1.Image = inBmp;
>             }
>         }
>     }
> }
> 

引用返信 編集キー/
■27790 / inTopicNo.18)  Re[12]: C#タイマーでのpictureBox.Image更新nitu
□投稿者/ フミ (8回)-(2008/11/14(Fri) 15:41:48)
No27721(Jitta様)へ返信

絵の更新部分setPicture()に関しては
もともとpictureBoxに絵を代入するあたりで、
エラー(>System.InvalidOperationException: オブジェクトは現在他の場所で使用されています。)
をだしていて、そこをエラーがでないようにするよう変更したかったので、
そのエラーがでやすいように下のように2つ連続で書きました。
なので実際には

>         //絵の更新用メソッド
>         private void setPicture()
>         {
>             SetBmp(Properties.Resources.aaaaa);//絵1
>         }

とひとつで行う予定です。

ちなみに上掲のプログラムにて2つの絵を10msで連続更新すると
更新自体は全く追いつかず、絵がチラチラしつつ描き変わる部分と描き変わらない部分が混ざりながら更新します。
ただ上記のエラーはでないです。
タイマーのスピードを調整すれば画面の更新はうまくいきます。

あと
■No27702で言った、
フォームを閉じたときのエラー
「破棄されたオブジェクトにアクセスできません。
 オブジェクト名 'Form1' です。」
ですが、
たぶんタイマーのイベント中にフォームが閉じられpictureBoxが破棄されてしまうために
出てくると思うのですが、
フラグ等を立てて防ごうとしましたが、
何ともなりませんでした。
しかたないので、
pictureBoxにイメージを代入するデリゲート内にtry-catchを追加して、
握りつぶすことにしました。。。。。
もっとちゃんとした解決法があればいいのですが。。。

こうしたらエラーなく画面更新がうまくいくようになったので、
あとはタイマーのスピードを調整すれば問題なさそうです。

とりあえず、まだもやもや部分が残っていますが解決ということに。。。
本当はこのtry-catch部分も改善したいですが。
何か情報あればお教え下さい。

ちなみに以下のようにデリゲート部分を変更しました。

        //画面表示用デリゲート
        private void SetBmp(Bitmap inBmp)
        {
            try
            {
                if (this.pictureBox1.InvokeRequired)
                {
                    SetImageCallback d = new SetImageCallback(SetBmp);
                    this.Invoke(d, new object[] { inBmp });
                }
                else
                {
                    this.pictureBox1.Image = inBmp;
                }
            }
            catch
            {
                //フォーム破棄時にObjectDisposedExceptionが出る可能性があるが、
                //対策が見つからないのでcatchでエラーを握りつぶす。。。。
            }
        }


解決済み
引用返信 編集キー/
■27823 / inTopicNo.19)  Re[13]: C#タイマーでのpictureBox.Image更新nitu
□投稿者/ Jitta on the way (225回)-(2008/11/15(Sat) 11:08:21)
No27790 (フミ さん) に返信
> ■No27721(Jitta様)へ返信
>
> 絵の更新部分setPicture()に関しては
> もともとpictureBoxに絵を代入するあたりで、
> エラー(>System.InvalidOperationException: オブジェクトは現在他の場所で使用されています。)
> をだしていて、そこをエラーがでないようにするよう変更したかったので、
> そのエラーがでやすいように下のように2つ連続で書きました。
> なので実際には
>
>> //絵の更新用メソッド
>> private void setPicture()
>> {
>> SetBmp(Properties.Resources.aaaaa);//絵1
>> }
>
> とひとつで行う予定です。
>
> ちなみに上掲のプログラムにて2つの絵を10msで連続更新すると
> 更新自体は全く追いつかず、絵がチラチラしつつ描き変わる部分と描き変わらない部分が混ざりながら更新します。
> ただ上記のエラーはでないです。
> タイマーのスピードを調整すれば画面の更新はうまくいきます。
>
> あと
> ■No27702で言った、
> フォームを閉じたときのエラー
> 「破棄されたオブジェクトにアクセスできません。
>  オブジェクト名 'Form1' です。」
> ですが、
> たぶんタイマーのイベント中にフォームが閉じられpictureBoxが破棄されてしまうために
> 出てくると思うのですが、
> フラグ等を立てて防ごうとしましたが、
> 何ともなりませんでした。
> しかたないので、
> pictureBoxにイメージを代入するデリゲート内にtry-catchを追加して、
> 握りつぶすことにしました。。。。。
> もっとちゃんとした解決法があればいいのですが。。。
>
> こうしたらエラーなく画面更新がうまくいくようになったので、
> あとはタイマーのスピードを調整すれば問題なさそうです。
>
> とりあえず、まだもやもや部分が残っていますが解決ということに。。。
> 本当はこのtry-catch部分も改善したいですが。
> 何か情報あればお教え下さい。


Closing イベントで、タイマーを止めればいいのでは?
引用返信 編集キー/
■28114 / inTopicNo.20)  Re[14]: C#タイマーでのpictureBox.Image更新nitu
 
□投稿者/ フミ (9回)-(2008/11/20(Thu) 00:45:31)
No27823 (Jitta on the way さん) に返信

closingイベントの中に
タイマーストップを入れたのですが、
ストップ後にやはりイベントが実行されてしまい、
描画用のピクチャーボックスはすでに破棄されていて、
エラーがでてしまいます。
ただ、MSDNのタイマーストップの場所には
メモとしてstop後にもイベントが起きる可能性があるから、
その辺注意して設計してね的なことが書いてあり、
さらにサンプルも載っているのですが、
上記のプログラムにどう適用してよいのかわかりませんでした。
http://msdn.microsoft.com/ja-jp/library/system.timers.timer.stop.aspx
うーむ。
引用返信 編集キー/

次の20件>
トピック内ページ移動 / << 0 | 1 >>

管理者用

- Child Tree -