- 締切済み
マウスを動かさないとパラパラ漫画が表示されない
Visual studio 2008 C#で作成しているプログラムの挙動がおかしくなる理由がわからないので、質問させて頂きます。 01、02、03と順に番号を振ってあるフォルダを読み込み、フォルダ内の画像をパラパラ漫画のように続けて表示させる、読み込みと再生を同時に行えるようにスレッドを使用したプログラムを作成しています。 「再生」ボタン押下→フォルダ01内の画像を連続表示→フォルダ02内の画像を連続表示→「次へ」ボタン押下→「再生」ボタン押下→フォルダ03内の画像を連続表示→フォルダ04内の画像を連続表示→「次へ」ボタン押下→「再生」ボタン押下… という風に全ての画像をpicturebox1に表示させていきたいのですが、再生ボタンを押してもpicturebox内に表示されず、何故かマウスを動かすと表示が始まります。 また、パラパラ漫画がガクガクとして滑らかに動かない時も同様に、マウスを動かすとなめらかに表示されます。 ガクガクとして滑らかに動かない時に、マウスを動かさないと、 >> //二回目スライドショーのスレッドを開始 >> thread_show = new Thread(new ThreadStart(threadShow)); の部分で InvalidOperationExeception がハンドルされる事があります。 自分でも調べてみたのですが、マウスを動かすとするすると動く理由が分かりません。読み込みと再生スレッドのタイマがうまく咬み合っていないのかと予想しているのですが…。 アドバイス頂けると嬉しいです。 //開始 private void プログラム開始ToolStripMenuItem_Click(object sender, EventArgs e) { //画像読み込みスレッドを開始 present = 0;//present:現在参照している動画像 directory = directories[show_order[present]];//show_order[]:フォルダの再生順序 thread_read = new Thread(new ThreadStart(read_image));//画像読み込みのスレッドthread_read宣言 thread_read.Start(); //再生ボタンを有効に thread_read.Join(); button2.Enabled = true; } //「再生」ボタンを押したとき private void button2_Click(object sender, EventArgs e) { Thread.Sleep(500); //一回目スライドショーのスレッドを開始 thread_show = new Thread(new ThreadStart(threadShow)); thread_show.Start(); //二回目画像読込の設定 if (present <= douga_num - 1) { directory = directories[show_order[present + 1]]; thread_read_one = new Thread(new ThreadStart(read_one_image)); thread_read_one.Start(); } thread_read_one.Join(); //二回目スライドショーのスレッドを開始 thread_show = new Thread(new ThreadStart(threadShow)); thread_show.Start(); thread_show.Join(); button3.Enabled = true;//「次へ」ボタンの表示 } //「次へ」ボタンを押したとき private void button3_Click(object sender, EventArgs e) { //回答フォームの表示 Form3 form = new Form3(this); form.ShowDialog(); if (form.DialogResult != DialogResult.OK) { return; } button3.Enabled = false; if (present < douga_num - 2 )//全動画像-2よりも参照動画番号が小さかったら { directory = directories[show_order[present+2]]; thread_read_one = new Thread(new ThreadStart(read_one_image)); thread_read_one.Start(); thread_read_one.Join(); } //再生ボタンを有効に if (present < douga_num) { button2.Enabled = true;//再生ボタンを有効に } present = present + 2;//参照している動画番号を2増やす //実験終了 if (present >= douga_num) { //再生ボタンを無効に button2.Enabled = false; } } //画像表示のスレッド private void threadShow() { Stopwatch sw = new Stopwatch(); //リストに入っているファイルの数をfile_numbersに入れる file_numbers = img.Count; pictureBox1.Image = img[0]; //フレーム番号のリセット now_show = 1; //時間計測:開始 sw.Start(); while (now_show < file_numbers) { if (33 <= sw.ElapsedMilliseconds) { //前フレームを消去 img[0].Dispose(); img.RemoveAt(0); //画像を表示 pictureBox1.Image = img[0]; //カウントを進める now_show++; //時間計測再スタート sw.Reset(); sw.Start(); }
- みんなの回答 (2)
- 専門家の回答
みんなの回答
- hidebun
- ベストアンサー率50% (92/181)
予想ですが、時間計測・画像指定を担当しているスレッドがCPUを専有して、再描画等を行うUIスレッドが動作不能な状態に陥っているのではないかと思います。 例えば、 pictureBox1.Reflesh(); Sleep(1); などとしてみると、挙動が変わるのではないでしょうか。 マウスを動かすと表示が改善されるのは、時間計測スレッドの専有が、マウス操作を契機にOSによって解放され、UIスレッドに制御が渡るためではないかと思います。 プログラムを見る限り、画像の表示時間がとてもクリティカルな要素に見えるのですが、(33ミリ秒で表示を切り替えることを期待している?)、なぜ画像の読み込みを裏でしながら、表示をするのでしょうか? このような時間制御に繊細なプログラムでは、表示以外の動作は極力行わないようにして、表示処理に専念させてあげないと、時間遅れが簡単に起こります。 最初に2セッション分の画像を読み込んでしまえるなら、そのようにした方が良いと思います。 また、上記のSleep(1)でも、要求は満たされないかもしれません。 高精度に時間制御を行うなら、スレッドの数は可能な限り少なくしましょう。
- hidebun
- ベストアンサー率50% (92/181)
画像を設定した後、再描画が必要なのでは? #マウスを被せると、その部分のグラフィックが汚れて、再描画が行われている //画像を表示 pictureBox1.Image = img[0]; pictureBox1.Refresh();
お礼
回答ありがとうございます。 再描画をしていなかったので、アドバイス頂いたように画像表示のループ内にReflesh();を記述したところ、マウスを動かさないと表示されないということはなくなりました。 ただ、二回再生する動画像のうち、最初だけ動きがガクガクとしており、これもマウスを動かすと治る(滑らかに再生される)ようなのですが原因がわかりません。 ループ内ではなく、pictureBox1.Image = img[0];の前にReflesh();の記述を行った時も同様の挙動になったので、Reflesh()が影響している訳では無さそうなのですが…。 引き続き、アドバイスを募集しております。