配列変数の値を順にLabelに表示していくには?

解決


R  2008-11-17 19:11:56  No: 145412  IP: 192.*.*.*

いつもお世話になります。

マイドキュメント以下のファイルをすべて取得して、順にLabel2に表示していくプログラムを作っているのですが
どうもうまくLabel2に表示できませんでした。
構文に誤りがありましたらご指導願います。

Public Sub GetAllFiles(ByVal folder As String, _
        ByVal searchPattern As String, ByRef files As ArrayList)
        Dim myName As String
        myName = SystemInformation.UserName
        folder = "C:\Documents and Settings\" + myName + "\My Documents"
        'folderにあるファイルを取得する
        Dim fs As String() = _
            System.IO.Directory.GetFiles(folder, searchPattern)
        'ArrayListに追加する
        files.AddRange(fs)

        'folderのサブフォルダを取得する
        Dim ds As String() = System.IO.Directory.GetDirectories(folder)
        'サブフォルダにあるファイルも調べる
        Dim d As String
        For Each d In ds
            GetAllFiles(d, searchPattern, files)
            Label2.Text = d.ToString 
            '5秒(5000ミリ秒)待機する
            System.Threading.Thread.Sleep(1000 * 5)
        Next d
    End Sub

編集 削除
R  2008-11-17 19:13:58  No: 145413  IP: 192.*.*.*

すいません。環境は.NET2003で.NETFramework1.1です。

編集 削除
魔界の仮面弁士  2008-11-17 20:06:56  No: 145414  IP: 192.*.*.*

Timer コントロールを用意して、5 秒ごとに次の要素を
表示させるような作りにしてみてください。

編集 削除
R  2008-11-18 16:31:42  No: 145415  IP: 192.*.*.*

コメントありがとうございます。
TimerコントロールのなかにFor..Nextを入れるとInterval毎に1ループ処理してくれるんでしょうか?

編集 削除
R  2008-11-18 18:03:22  No: 145416  IP: 192.*.*.*

参考にするHPをかえてみて、やり直したところいいところまではいけたんですが・・・

    Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        ' 取得したファイル名を列挙する
        For Each stFilePath As String In stFilePathes
            Label2.Text = stFilePath + " をコピー(外部へインポート)中..."
            System.Threading.Thread.Sleep(100)
            Application.DoEvents()
        Next stFilePath

    End Sub

(Timer1のTickは5000とする)
とすると、For..Nextは100ミリ秒待機を入れても処理してくれるのですが、
Timer1のTickに達するとstFilePathがはじめに戻ってしまいます。
かといってTickを99999999とかに設定するとイベントが始まらないので。。。
できればFor..Nextを使わずにEach..In..の働きをする構文をTimerイベントの中で使用したいと思っています。
ご指導お願いします。


ちなみにこれはジョークプログラムです(笑
UP先:http://ishisuke007.yh.land.to/BeingHacked.exe

編集 削除
R  2008-11-18 18:06:07  No: 145417  IP: 192.*.*.*

補足:現段階では終了したいときはタスクマネージャから「BeingHacked.exe」終了でお願いします。

編集 削除
魔界の仮面弁士  2008-11-18 18:37:56  No: 145418  IP: 192.*.*.*

> TimerコントロールのなかにFor..Nextを入れると

入れません。Tick イベントそのものがループ待機の処理と思ってください。

突然登場した stFilePathes というのが、String 配列の事であれば、
  1回目の Tick イベントでは、stFilePathes(0) を表示
  2回目の Tick イベントでは、stFilePathes(1) を表示
  3回目の Tick イベントでは、stFilePathes(2) を表示
      :
のように処理させれば OK です。イメージとしてはこんな感じ。

  Private pathIndex As Integer = 0
  Private Sub Timer1_Tick(…
    Dim stFilePathe As String = stFilePathes(pathIndex)
    Label2.Text = stFilePathe & " をコピー(外部へインポート)"

    '次の番号にすすめる
    pathIndex += 1

    '配列を全て出力したら、タイマーを止める
    If pathIndex > UBound(stFilePathes) Then
      pathIndex = 0
      Timer1.Enabled = False
    End If
  End Sub



> For..Nextは100ミリ秒待機を入れても処理してくれるのですが
ループさせる / Sleep させるという発想から離れてください。
画面を持つスレッドを Sleep させるべきではありません。

また、描画処理の多くは メソッドの実行が行われていない空き時間に
行われます。そのため、長いループ処理の最中などに Label 等を書き換えても、
その結果は、基本的にはメソッドの終了が終わるまで画面に反映されません。

DoEvents を行うことで、割り込んで処理させる事はできますが、
処理が複雑化しやすいので、これもできれば避けた方が良いでしょう。
そもそも、待機させるようなコードにしなければ、DoEvents を呼ぶ必要もないですし。

編集 削除
R  2008-11-19 16:19:43  No: 145419  IP: 192.*.*.*

ご丁寧な指導ありがとうございます。
試してみたところ、うまく作動しました。

> 1回目の Tick イベントでは、stFilePathes(0) を表示
> 2回目の Tick イベントでは、stFilePathes(1) を表示
> 3回目の Tick イベントでは、stFilePathes(2) を表示

↑まさにそうですね、これが求めていた処理でした。
魔界の仮面弁士さん、ありがとうございました。

編集 削除