tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルBackgroundWorkerの使い方で教えてください
記事No9633
投稿日: 2009/11/27(Fri) 14:56
投稿者kanmi
下記のようにコードを書きましたが、バックグラウンド処理がうまくできてない気がします。
時間のかかる処理が終わってからプログレスバーが動き出しているように見えるのですが気のせいでしょうか?

btnOK_Click
   '時間のかかる処理を別スレッドで開始
    bgWorker.RunWorkerAsync(100)            'DoWorkイベント開始

bgWorker_DoWork
    Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
    'EXCEL出力処理
     XlsOut(worker)  <---- 時間のかかる処理
    
     For i As Integer = 1 To CInt(e.Argument)
       If worker.CancellationPending = True Then
          e.Cancel = True
          Exit Sub
        End If
        '進捗状況の報告
        Dim percentage As Integer = CInt(i * MaxPercent / CInt(e.Argument)) '進捗率
        worker.ReportProgress(percentage)       'ProgressChangedイベント発生
        System.Threading.Thread.Sleep(100)
    Next
    e.Result = "すべて完了"

[ツリー表示へ]
タイトルRe: BackgroundWorkerの使い方で教えてください
記事No9634
投稿日: 2009/11/27(Fri) 15:10
投稿者YuO
> 下記のようにコードを書きましたが、バックグラウンド処理がうまくできてない気がします。
> 時間のかかる処理が終わってからプログレスバーが動き出しているように見えるのですが気のせいでしょうか?

DoWorkのハンドラの中は,シングルスレッドの場合と同じく順番に処理されていきます。
つまり,XlsOutに時間がかかる場合,XlsOutが終了するまでその次のループには移動しません。

XlsOut中で進捗するたびにReportProgressを呼び出したり,
キャンセル処理をするようにする必要があります。

[ツリー表示へ]
タイトルRe^2: BackgroundWorkerの使い方で教えてください
記事No9635
投稿日: 2009/11/27(Fri) 15:16
投稿者kanmi
早速のご回答、ありがとうございます。

> DoWorkのハンドラの中は,シングルスレッドの場合と同じく順番に処理されていきます。
> つまり,XlsOutに時間がかかる場合,XlsOutが終了するまでその次のループには移動しません。

やっぱりそうですか・・・

> XlsOut中で進捗するたびにReportProgressを呼び出したり,
> キャンセル処理をするようにする必要があります。

では、時間のかかる処理(何秒か何分か不定)をプログレスバーで表示するのは無理なのでしょうか?  なにかいい方法をご存知でしたら教えてください。

[ツリー表示へ]
タイトルRe^3: BackgroundWorkerの使い方で教えてください
記事No9637
投稿日: 2009/11/27(Fri) 16:49
投稿者魔界の仮面弁士
> 時間のかかる処理(何秒か何分か不定)をプログレスバーで表示するのは無理なのでしょうか?  なにかいい方法をご存知でしたら教えてください。

その“時間のかかる処理”には、
  「全体の何パーセントまで完了したのか」
  「全工程のうち、何段階目まで処理されているか」
などを知る方法が用意されていますか?

用意されていないのであれば、
 (案1) ProgressBar の Style を Marquee にして代用する。(要VisualStyle)
 (案2) 進捗表示は諦め、単に経過秒数のみを表示するだけにとどめる。
などで誤魔化すという手もあるかと思います。

[ツリー表示へ]
タイトルRe^4: BackgroundWorkerの使い方で教えてください
記事No9638
投稿日: 2009/11/27(Fri) 17:06
投稿者kanmi
ご回答ありがとうございます。

> その“時間のかかる処理”には、
>   「全体の何パーセントまで完了したのか」
>   「全工程のうち、何段階目まで処理されているか」
> などを知る方法が用意されていますか?
  
  処理の中は、いくつかの処理の塊なので、半分くらい終わったとか大まかなことは
  わかりますが、1%単位でのプログレスの表示には対応できそうにありません。
>
> 用意されていないのであれば、
>  (案1) ProgressBar の Style を Marquee にして代用する。(要VisualStyle)
>  (案2) 進捗表示は諦め、単に経過秒数のみを表示するだけにとどめる。
> などで誤魔化すという手もあるかと思います。
  
  そうですね・・・。
  キャンセルボタン押下も時間のかかる処理に埋め込んだ場所でしか取れなくなる
  のですよね・・・。悲しいです。
  希望としては、時間のかかる処理を行いながら、いつでもキャンセル可能で、その上
  バーが進んでいくのができるのがバックグラウンド処理かと勘違いしてました。


[ツリー表示へ]
タイトルRe^5: BackgroundWorkerの使い方で教えてください
記事No9643
投稿日: 2009/11/27(Fri) 20:26
投稿者魔界の仮面弁士
>   処理の中は、いくつかの処理の塊なので、半分くらい終わったとか大まかなことは
>   わかりますが、1%単位でのプログレスの表示には対応できそうにありません。

大まかでも良いと思いますよ(もちろん、細かく表せるならその方が良いですが)。

「0% から 1% に増加するのに要する時間」と
「1% から 2% に増加するのに要する時間」が違っていても良いですし、
増加単位が 1% 単位でなければならないという制限もありませんから。


>   キャンセルボタン押下も時間のかかる処理に埋め込んだ場所でしか取れなくなる
>   のですよね・・・。悲しいです。
「キャンセルされたら、以降の処理を中断する。」という実装のほかに、
「キャンセルされたら、そのスレッドの存在は無視して、新しいスレッドを作る」という
実装方法もあるかも知れません。やりたい内容にもよりますけれども。


>   希望としては、時間のかかる処理を行いながら、いつでもキャンセル可能で、その上
>   バーが進んでいくのができるのがバックグラウンド処理かと勘違いしてました。
キャンセル可能かどうかや、進捗表示が可能かどうかは別の話ですね。

たとえば、レストランの流れを想像してみてください。

厨房で料理が作られている間(バックグラウンド処理)にも、
フロアスタッフは、接客作業(メイン処理)を行う事が出来ますよね。

この時、厨房のスタッフが、フロアスタッフに料理の進捗状況を逐次伝える必要があるか、
それとも、出来上がった時点で料理の完成を伝えるのみで良いのか、という違いがあっても
それぞれのスタッフが並行で自分の作業をこなす事ができる点では変わりませんよね。

[ツリー表示へ]
タイトルRe^6: BackgroundWorkerの使い方で教えてください
記事No9650
投稿日: 2009/11/30(Mon) 08:51
投稿者kanmi
大変わかりやすい例まであげて説明していただいてありがとうございます。

> たとえば、レストランの流れを想像してみてください。
>
> 厨房で料理が作られている間(バックグラウンド処理)にも、
> フロアスタッフは、接客作業(メイン処理)を行う事が出来ますよね。
>
> この時、厨房のスタッフが、フロアスタッフに料理の進捗状況を逐次伝える必要があるか、
> それとも、出来上がった時点で料理の完成を伝えるのみで良いのか、という違いがあっても
> それぞれのスタッフが並行で自分の作業をこなす事ができる点では変わりませんよね。

そういう考えで行くと、重い処理を厨房で、進捗状況をフロアで行って、もし、料理ができなかったら95%くらいでとまってて、料理ができてから100%でもOKかなと思ってます。
このやり方をちょっとコーディングしてみたいと思います。
いろいろありがとうございました。

[ツリー表示へ]