none
ProgressBarについて RRS feed

  • 質問

  • こんばんは。

    ProgressBarを汎用的に使用しようと、それのみを貼り付けたフォームをひとつ用意しました。

    いろいろと調べた結果、バックグラウンドで処理を行うことも可能であり、DoWorkイベントの
    ReportProgressに値を入れることにより、ProgressBarを進行させることができることまで
    まずは、ひとつの処理を行うことができるようになりました。
    (おそらく、説明がおかしいと思いますが、ご容赦ください)

    そこで、ProgressBarを貼り付けたフォームに外部から進行用のカウントを投げることができないかと思い
    質問をさせていただきました。

    自分がインターネットなどで調べた際は、必要なデータなどをProgressBarを貼り付けたフォームに
    引数として渡し、このフォーム内で処理をして、結果を元のフォームに戻す必要があるように受け取れたのですが、
    その解釈でよいのでしょうか。

    それとも、処理はもとのフォームで行い、ProgressBarを進行させるための値のみをProgressBarを貼り付けた
    フォームに渡すという方法が一般的なのでしょうか。

    質問がわかりにくいとは思いますが、どうかアドバイスお願いします。

     

    2011年8月21日 13:19

回答

  • それとも、処理はもとのフォームで行い、ProgressBarを進行させるための値のみをProgressBarを貼り付けた
    フォームに渡すという方法が一般的なのでしょうか。


    こちらの方が使いやすいと思います。理由はAzuleanさんが書かれていることと同じです。
    BackgroundWorkerのProgressChangedイベントハンドラで、それとは別の汎用的なProgressBarを持ったフォームに対して、ProgressBar.Valueプロパティを更新すれば良いだけだと思います。
    汎用的なProgressBarはUIスレッド上で開いて下さい。DoWorkイベントハンドラではダメです。以下が詳しいので参考になると思います。

    (参考)
    Part 4. Visual Studio によるマルチスレッドアプリの開発
    http://blogs.msdn.com/b/nakama/archive/2009/04/09/part-4-visual-studio.aspx

    また、以前のスレッドの続きということでよろしいでしょうか?このスレッドは何となく中途半端に終わっているような気がするのですが・・・

    プログレスバーを汎用的に使用するには
    http://social.msdn.microsoft.com/Forums/ja-JP/vbexpressja/thread/7b72869f-d904-4ebc-b7e3-09ec72cc7899/

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    2011年8月22日 16:58
    モデレータ
  • 自分がインターネットなどで調べた際は、必要なデータなどをProgressBarを貼り付けたフォームに
    引数として渡し、このフォーム内で処理をして、結果を元のフォームに戻す必要があるように受け取れたのですが、
    その解釈でよいのでしょうか。

    それとも、処理はもとのフォームで行い、ProgressBarを進行させるための値のみをProgressBarを貼り付けた
    フォームに渡すという方法が一般的なのでしょうか。

    一般解がどうということは言いがたいのですが、前者のやり方は汎用性がないように思えました。
    結局、何らかのデリゲートを渡して、その中で ReportProgress 相当のメソッド呼び出しが必要になり、あまり使いやすいとは思えないためです。

    そうであれば、後者の ProgressBar.Value 相当を公開するフォームとして割り切った方がよいかなと考えています。

    public int ProgressBarMaximum { get { return progressBar1.Maximum; } set { progressBar1.Maximum = value; }
    public int ProgressBarMinimum { get { return progressBar1.Minimum; } set { progressBar1.Minimum = value; }
    public int ProgressBarValue { get { return progressBar1.Value; } set { progressBar1.Value = value; }
    このようなコードをフォームに書いてしまうイメージ。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2011年8月21日 13:56
    モデレータ
  •  「処理が進んだ」というイベントを用意し、そのイベント ハンドラで ProgressBar の進捗を進める、ということをやっています。


    Jitta@わんくま同盟
    2011年8月22日 15:10

すべての返信

  • 自分がインターネットなどで調べた際は、必要なデータなどをProgressBarを貼り付けたフォームに
    引数として渡し、このフォーム内で処理をして、結果を元のフォームに戻す必要があるように受け取れたのですが、
    その解釈でよいのでしょうか。

    それとも、処理はもとのフォームで行い、ProgressBarを進行させるための値のみをProgressBarを貼り付けた
    フォームに渡すという方法が一般的なのでしょうか。

    一般解がどうということは言いがたいのですが、前者のやり方は汎用性がないように思えました。
    結局、何らかのデリゲートを渡して、その中で ReportProgress 相当のメソッド呼び出しが必要になり、あまり使いやすいとは思えないためです。

    そうであれば、後者の ProgressBar.Value 相当を公開するフォームとして割り切った方がよいかなと考えています。

    public int ProgressBarMaximum { get { return progressBar1.Maximum; } set { progressBar1.Maximum = value; }
    public int ProgressBarMinimum { get { return progressBar1.Minimum; } set { progressBar1.Minimum = value; }
    public int ProgressBarValue { get { return progressBar1.Value; } set { progressBar1.Value = value; }
    このようなコードをフォームに書いてしまうイメージ。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2011年8月21日 13:56
    モデレータ
  •  「処理が進んだ」というイベントを用意し、そのイベント ハンドラで ProgressBar の進捗を進める、ということをやっています。


    Jitta@わんくま同盟
    2011年8月22日 15:10
  • それとも、処理はもとのフォームで行い、ProgressBarを進行させるための値のみをProgressBarを貼り付けた
    フォームに渡すという方法が一般的なのでしょうか。


    こちらの方が使いやすいと思います。理由はAzuleanさんが書かれていることと同じです。
    BackgroundWorkerのProgressChangedイベントハンドラで、それとは別の汎用的なProgressBarを持ったフォームに対して、ProgressBar.Valueプロパティを更新すれば良いだけだと思います。
    汎用的なProgressBarはUIスレッド上で開いて下さい。DoWorkイベントハンドラではダメです。以下が詳しいので参考になると思います。

    (参考)
    Part 4. Visual Studio によるマルチスレッドアプリの開発
    http://blogs.msdn.com/b/nakama/archive/2009/04/09/part-4-visual-studio.aspx

    また、以前のスレッドの続きということでよろしいでしょうか?このスレッドは何となく中途半端に終わっているような気がするのですが・・・

    プログレスバーを汎用的に使用するには
    http://social.msdn.microsoft.com/Forums/ja-JP/vbexpressja/thread/7b72869f-d904-4ebc-b7e3-09ec72cc7899/

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    2011年8月22日 16:58
    モデレータ
  • ご回答ありがとうございます。

    しばらく、プログラミングから離れていたので、以前の質問をすっかりと忘れていました。
    大変、失礼をいたしました。

    皆様のご回答や、提示されたページなどを読み、いろいろ考えていたところ、根本的な間違いを
    起こしている気がします。

    ProgressBarコントロールを配置した、フォームを一つ用意してあるのですが、もともと一つの
    処理を行うためだけに用意をしていたので、このフォームにBackgroundWorkerをセットしていました。

    しかし、よく考えてみると、もともとの処理を行っているフォームにBackgroundWorkerはセットすべきでは
    ないかと思うようになりました。

    この方向で今一度、考えてみたいと思います。

    もし、この考え方が間違っていましたら、ご指摘いただけると幸いです。

    2011年8月23日 2:42
  • しかし、よく考えてみると、もともとの処理を行っているフォームにBackgroundWorkerはセットすべきでは
    ないかと思うようになりました。

    ちまたにあるサンプルは説明を簡単にするために、ほとんどが1つのフォーム上にProgressBarとBackgroundWorkerを配置しています。これはProgressBarはUIスレッドで、BackgroundWorkerのDoWorkイベントハンドラはプールスレッドで動きますが、その例を簡単に示すために1つのフォームに記述しているに過ぎません。
    したがって、必ずしも1つのフォームに記述する必要はなく、汎用のProgressBarを持つフォームは、ProgressBarのみを持つだけでもかまいません。そこにAzuleanさんが書かれたようなプロパティを設けます。別のフォームで、例えばボタンClickイベントハンドラでその汎用ProgressBarフォームを開き、Azuleanさんが示されたようなプロパティ経由でProgressBarに対する初期設定を行った後、BackgroundWorkerのRunWorkerAsyncメソッドで処理を開始し、DoWorkイベントハンドラ内でReportProgressメソッドを実行し、ProgressChangedイベントハンドラ内で、汎用ProgressBarフォームのProgressBarのValueプロパティを更新する流れでもかまいません。
    ポイントとしては、どの処理がどのスレッドで実行されているのかをきちんと把握し、プールスレッドからUIスレッドを直接操作してはいけないというルールを守ることです。そうすれば上記に上げた例だけではなく、いろいろ応用ができると思います。

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    2011年8月23日 3:18
    モデレータ