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

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

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

Re[3]: BackGroundWorで画像切り替えを行いたい。


(過去ログ 62 を表示中)

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

■35936 / inTopicNo.1)  BackGroundWorで画像切り替えを行いたい。
  
□投稿者/ hs (37回)-(2009/05/15(Fri) 23:00:30)

分類:[VB.NET/VB2005 以降] 

いつもお世話になってます。

VS2008 VBで開発しています。

現在、動画を再生するAPを開発しているのですが、動画を読み込むのに10秒近くかかっています。
その間、Load画像みたいなものを作って表示しようとしているのですが、スレッドにたどり着きいろいろと試行錯誤しております。
そこで容易に扱える BackGroundWorker を見つけて早速試してみました。
ピクチャーボックスを10個用意して0〜9の画像の可視を単純に変更しているPGです。

Private Sub BgWork_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BgWork.DoWork
Dim rNum As Integer = 0 '表示画像保持用
  'PictureBoxの配列宣言・格納
Dim pictWait() As PictureBox = {F_Waiting.Pict0, F_Waiting.Pict1, F_Waiting.Pict2, F_Waiting.Pict3, _
F_Waiting.Pict4, F_Waiting.Pict5, F_Waiting.Pict6, F_Waiting.Pict7, _
F_Waiting.Pict8, F_Waiting.Pict9}
Do
      'いったんすべての画像の可視をFalse
For i = 0 To 16    
pictWait(i).Visible = False
Next
      '表示する画像のみTrue
pictWait(rNum).Visible = True
rNum += 1
If rNum > 16 Then rNum = 0
    Loop
End Sub

上記の部分を動画を再生するフォームのLord時にRunWorkerAsync()で呼び出し、読み込み完了時にCancelAsync()で中断しています。
単純に読み込みする際、開発しているPCのスペックの問題なのか、画像の切り替えが画面に反映されなく表示部分だけ真っ黒になったままです。なにか良いアイディアないでしょうか?

ちなみにWebではよく読み込み中の画像(映像?)を見かけるのですが、市販やフリーのソフトではプログレスバー以外の手法を見かけたことはありません。やはり皆さんはいろいろと試した結果、一番無難な手法ということなのでしょうか?
引用返信 編集キー/
■35939 / inTopicNo.2)  Re[1]: BackGroundWorで画像切り替えを行いたい。
□投稿者/ Azulean (374回)-(2009/05/15(Fri) 23:21:12)
No35936 (hs さん) に返信
> 単純に読み込みする際、開発しているPCのスペックの問題なのか、画像の切り替えが画面に反映されなく表示部分だけ真っ黒になったままです。なにか良いアイディアないでしょうか?
その画面を更新する処理はメインスレッドで行われます。(大抵の場合)
裏で動くBackgroundWorkerで表示状態を制御しても、画面が更新されないので残念ながら効果がありません。

BackgroundWorkerを使う場合、DoWorkイベントで重たい処理や裏で実行したい処理を書きます。
メインスレッドでUIの更新、進捗の更新、アニメーションの表示を担当させることになります。
引用返信 編集キー/
■35941 / inTopicNo.3)  Re[1]: BackGroundWorで画像切り替えを行いたい。
□投稿者/ 魔界の仮面弁士 (1069回)-(2009/05/15(Fri) 23:26:19)
No35936 (hs さん) に返信
> ピクチャーボックスを10個用意して0〜9の画像の可視を単純に変更しているPGです。
ワーカースレッド(この場合は DoWork イベント)の中から、コントロールを直接操作してはいけません。
コントロールの操作は、メインとなる UI スレッドから行う必要があります。

> ちなみにWebではよく読み込み中の画像(映像?)を見かけるのですが、
PictureBox に非同期での読み込みを行わせたいのあれば、
PictureBox の LoadAsync メソッドを利用してみてください。
この場合、読み込み中の画像には InitialImage プロパティが利用されます。
引用返信 編集キー/
■35942 / inTopicNo.4)  Re[1]: BackGroundWorで画像切り替えを行いたい。
□投稿者/ 渋木宏明(ひどり) (1155回)-(2009/05/15(Fri) 23:26:26)
渋木宏明(ひどり) さんの Web サイト
> 単純に読み込みする際、開発しているPCのスペックの問題なのか、画像の切り替えが画面に反映されなく表示部分だけ真っ黒になったままです。なにか良いアイディアないでしょうか?

おろらく手法に問題があるので、手法を見直してください。

まず、Windows の画面描画の仕組みを理解しましょう。

動画の読み込み処理とやらを、プライマリスレッドで実行していませんか?

Windows では、通常はウィンドウの描画・再描画処理はアプリケーション(のプライマリスレッド)が担当します。

プライマリスレッドがファイルの読み込み処理にかかりきりになってしまっていたら、ワーカースレッドでピクチャボックスを差し替えてみても、画面上にその操作の結果は反映されません。

この場合、ファイルの読み込み処理こそをバックグラウンドで実行するべきなのです。

> ちなみにWebではよく読み込み中の画像(映像?)を見かけるのですが、市販やフリーのソフトではプログレスバー以外の手法を見かけたことはありません。やはり皆さんはいろいろと試した結果、一番無難な手法ということなのでしょうか?

別にそんなことはないと思いますよ。

エクスプローラですら、ファイルコピー時にアニメーション表示しているので。

引用返信 編集キー/
■35944 / inTopicNo.5)  Re[1]: BackGroundWorで画像切り替えを行いたい。
□投稿者/ Hongliang (383回)-(2009/05/15(Fri) 23:36:38)
DoWork の中で GUI を触っちゃいけません。BackgroundWorker で GUI を触る場合、ReportProgress を呼び出して ProgressChanged イベントを発生させ、このイベント内で GUI を触るようにしてください。

お書きのでいくなら、
・PictureBox 配列はフィールドに置いておいて Load で初期化する
・DoWork でループを回し、ReportProgress に rNum を渡す
・ProgressChanged で、受け取った rNum の PictureBox とそれ以外の PicureBox の Visible を操作する
みたいな感じで。あと、適当に DoWork 内で Thread.Sleep のウェイト入れないと大変なことになるかと思います。
ただ、この PictureBox ってパラパラ漫画みたいな感じなんですか? それなら PictureBox 十個用意するんじゃなくて、Image オブジェクトを十個用意して PictureBox の Image プロパティを切り替えた方が楽だと思いますが……。

> ちなみにWebではよく読み込み中の画像(映像?)を見かけるのですが、市販やフリーのソフトではプログレスバー以外の手法を見かけたことはありません。やはり皆さんはいろいろと試した結果、一番無難な手法ということなのでしょうか?
ローカル環境なら時間の目安もつきやすいですし。
プログレスバーは基本的な GUI ですから万人に理解しやすいのは大きな利点でしょう。
引用返信 編集キー/
■35946 / inTopicNo.6)  Re[2]: BackGroundWorで画像切り替えを行いたい。
□投稿者/ hs (38回)-(2009/05/16(Sat) 01:21:29)
皆さん早速たくさんの回答ありがとうございます。

□投稿者/ Azulean
>裏で動くBackgroundWorkerで表示状態を制御しても、画面が更新されないので残念ながら効果がありません。
>BackgroundWorkerを使う場合、DoWorkイベントで重たい処理や裏で実行したい処理を書きます。
この場合、DoWorkイベントでは時間のかかる動画ファイルの読込みの命令をやらせておき、読込が完了するまで
Dim pictWait() As PictureBox 部分をメインスレッドで行えば行けそうですね。
早速明日試してみます。

□投稿者/ 魔界の仮面弁士
>ワーカースレッド(この場合は DoWork イベント)の中から、コントロールを直接操作してはいけません。
確かに書籍にその事が書いてありました;
しかしその書籍のサンプルソースに上記の事を書いているにも関わらず、DoWork イベントでコントロールを直接操作しているサンプルソースで大変混乱していました。もちろん同じソースを実行した結果、「別のスレッドからはアクセスできません。.....」とエラーになりました。

□投稿者/ 渋木宏明(ひどり)
>動画の読み込み処理とやらを、プライマリスレッドで実行していませんか?
たしかに Private Sub BgWork_DoWork 自体は主スレッドで呼び出しています。しかし、BgWork_DoWork()を呼び出してもBgWork_DoWork()が呼び出されたと同時にBgWork_DoWork()自体は別スレッドでDoWorkイベントに記述した命令を実行し、BgWork_DoWork()以降の命令は主スレッドでとして主スレッドとBgWork_DoWork()部分がマルチで動いているものだと理解しています。
>この場合、ファイルの読み込み処理こそをバックグラウンドで実行するべきなのです。
Azuleanさんのも参考に明日早速試してみます。

□投稿者/ Hongliang
>ただ、この PictureBox ってパラパラ漫画みたいな感じなんですか?
その通りです。
>それなら PictureBox 十個用意するんじゃなくて、Image オブジェクトを十個用意して PictureBox の Image プロパティを切り替えた
>方が楽だと思いますが……。
実はImageListに上記の十個ある画像を格納しImage プロパティを変更するつもりで組んでいたのですが、ImageListにはアイコン形式のファイルでないと正常に格納できず...で、フルパスでと思いFromFile()?だったかなぁ?で試そうとしているうちに寄り道してしまい質問の内容にたどりついていました。ループ部分(画像切替)は、明日書き直したいと思います。

引用返信 編集キー/
■35964 / inTopicNo.7)  Re[3]: BackGroundWorで画像切り替えを行いたい。
□投稿者/ hs (39回)-(2009/05/16(Sat) 20:43:37)
皆さんありがとうございました。

今回は、BackgroundWorkerをはじめて使用してみてかなり躓きましたが、何とか無事に完成しました。

アドバイス頂いたとおりに動画ファイルの読込をBackgroundWorkerで行い、画像の切替をメインスレッドで行うようにしました。
また、動画ファイルの読込時にも多少UIを操作する部分があったのでDoWorkイベントではなく、RunWorkerCompleted(終了時)に行うようにしました。
また1つ勉強させていただきました。m_ _m

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -