none
実行中の動作 RRS feed

  • 質問

  • プログラム実行中に、formを動かしてしまうと作業がストップしてしまうので困っています。
    (タスクマネージャで応答なしの状態)
    また、他のアプリケーションを動かしても同様な現象が起きます。
    どなかた心当たりのあるかたサポートお願いします。

    プログラムは大量ファイルの数値データを読み込むものです。
    2009年5月14日 5:51

回答

  • まずは、MSDNライブラリでの検索。次に、検索エンジンで検索すればいくらでも情報がヒットします。

    この記事が分かりやすい方ではないかと思います。
    http://www.atmarkit.co.jp/fdotnet/dotnettips/436bgworker/bgworker.html
    • 回答としてマーク ワカRUN 2009年5月15日 1:07
    2009年5月14日 8:09
  • プログラム実行中に、formを動かしてしまうと作業がストップしてしまうので困っています。
    (タスクマネージャで応答なしの状態)
    Windowsで動くアプリケーションというのは、一定時間毎に画面を更新したり、マウスの移動イベントを受け取ったり、キーボードの入力を受け取ったりという、"様々な処理"をする必要があります。
    今回、「大量ファイルの数値データを読み込む」といった非常に時間のかかる処理を書かれていますので、前述のような"様々な処理"がずっと順番待ちのままになります。
    この順番待ちの状態が長く続いていると、Windows XP以降のOSでは真っ白のウィンドウになったり、応答なしと表示されます。


    よくある解決策としては、長くかかる処理を別スレッドで実行する方法(前者)と、処理を分割してタイマーイベントで続きをする方法(後者)ですね。
    本質的には前者で解決するべきです。

    前者は"様々な処理"と同時に時間のかかる処理を並行させる方法です。
    BackgroundWorkerというキーワードが出ていますので、それについて調べてみて下さい。

    後者はちょっと処理をしては、"様々な処理"をさせる余裕を与えて、またちょっと処理するということを繰り返します。
    例えば、100個の処理があるとしたら、5個実行して抜けて、1秒ごとのTimer_Tickが来たら次の5個を処理することを繰り返して、"様々な処理"を実行する余裕を与えてあげるやり方です。


    いずれにしても、スレッドやタイマーといった仕組みを知っていないと、意図せぬ動きをするプログラムになることがあります。
    何らかの書籍を購入して勉強される等、体系的に学べるようにしましょう。
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    • 回答としてマーク ワカRUN 2009年5月15日 1:07
    2009年5月14日 14:18
    モデレータ

すべての返信

  • 具体的なコードを拝見していないので、断言はできませんが、処理は続いているのだと思いますよ。

    こうしたコストの高い処理を行う場合、BackgroundWorkerで非同期処理を行うのが良いと思います。ProgressBarに進捗率を表示するとより分かりやすいインタフェースになるのではないでしょうか?
    2009年5月14日 6:53
  • 作業がとまっているのではなく、処理をしているのでFormへの操作には反応できませんという意味だと思います。
    よって、作業がストップしているわけではありませんので困る必要はないかと。

    もし、作業が本当にとまっているのであれば別の問題が考えられますが、これは一般的な現象ではないためコードが示されていないため具体的な目星がつきません。



    http://blogs.wankuma.com/hatsune/
    2009年5月14日 6:57
  • すいません。
    1時間勉強しましたが、結局BackgroundWorkerがわかりませんでした。

    何か簡単なサンプルコードはありますでしょうか?
    宜しくお願いします。
    2009年5月14日 7:58
  • まずは、MSDNライブラリでの検索。次に、検索エンジンで検索すればいくらでも情報がヒットします。

    この記事が分かりやすい方ではないかと思います。
    http://www.atmarkit.co.jp/fdotnet/dotnettips/436bgworker/bgworker.html
    • 回答としてマーク ワカRUN 2009年5月15日 1:07
    2009年5月14日 8:09
  • プログラム実行中に、formを動かしてしまうと作業がストップしてしまうので困っています。
    (タスクマネージャで応答なしの状態)
    Windowsで動くアプリケーションというのは、一定時間毎に画面を更新したり、マウスの移動イベントを受け取ったり、キーボードの入力を受け取ったりという、"様々な処理"をする必要があります。
    今回、「大量ファイルの数値データを読み込む」といった非常に時間のかかる処理を書かれていますので、前述のような"様々な処理"がずっと順番待ちのままになります。
    この順番待ちの状態が長く続いていると、Windows XP以降のOSでは真っ白のウィンドウになったり、応答なしと表示されます。


    よくある解決策としては、長くかかる処理を別スレッドで実行する方法(前者)と、処理を分割してタイマーイベントで続きをする方法(後者)ですね。
    本質的には前者で解決するべきです。

    前者は"様々な処理"と同時に時間のかかる処理を並行させる方法です。
    BackgroundWorkerというキーワードが出ていますので、それについて調べてみて下さい。

    後者はちょっと処理をしては、"様々な処理"をさせる余裕を与えて、またちょっと処理するということを繰り返します。
    例えば、100個の処理があるとしたら、5個実行して抜けて、1秒ごとのTimer_Tickが来たら次の5個を処理することを繰り返して、"様々な処理"を実行する余裕を与えてあげるやり方です。


    いずれにしても、スレッドやタイマーといった仕組みを知っていないと、意図せぬ動きをするプログラムになることがあります。
    何らかの書籍を購入して勉強される等、体系的に学べるようにしましょう。
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    • 回答としてマーク ワカRUN 2009年5月15日 1:07
    2009年5月14日 14:18
    モデレータ
  • キャンセルボタンの使い方を追加しました。
    参考にどうぞ。
    090521 16:25
     

    GX999さんありがとうございました。
    また、Azuleanさんのわかりやすい説明で、フリーズの意味もわかってきました。
    ありがとうございます。

    初めての質問でしたので、こんなにも返答が速いことに驚きました。

    このコーナーではBackgroundWorkerについての掲示板が少ない気がしたので、
    以下に作業していたプログラムの一部を公開します。

    ・個人情報の部分は「?」にしています。
    ・BackgroundWorkerに関する部分は太字にしています。
    ・VB6.0と混ざっている部分もあり、かなり分かりにくいのですが一応流れます。

    '----------------------------------------------
      Public nmD As Integer
        Public counter As System.Collections.ObjectModel.ReadOnlyCollection(Of String)

    Private Sub Button7_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button7.Click
            '-----------------
            'ここからTAB2のプログラム
            '-----------------
        Button7.Enabled = False 'コントロール無効
            TabControl1.Enabled = True
            Button6.Visible = True
            Button6.Enabled = True 'コントロールの操作は先にやること。      

           'MsgBox("CHECKを開始します" & vbCrLf & "CHECK中は何もを動かさないで下さい。",     MsgBoxStyle.Exclamation, "注意")

            Url = "???"

            If RadioButton4.Checked = True Then
                Url2 = Url & "H12世界測地系\"
                Label4.Text = RadioButton4.Text

                counter = My.Computer.FileSystem.GetDirectories(Url & "H12世界測地系")
                nmD = counter.Count
            Else RadioButton5.Checked = True Then
                Url2 = Url & "H12日本測地系\"
                Label4.Text = RadioButton5.Text

                counter = My.Computer.FileSystem.GetDirectories(Url & "H12日本測地系")
                nmD = counter.Count
             End If


            ProgressBar2.Visible = True
            ProgressBar2.Minimum = 0
            ProgressBar2.Maximum = 100
            ProgressBar2.Value = 0
            ProgressBar2.Step = 1


            If My.Computer.FileSystem.FileExists _
                        ("C:\???file.txt") = True Then
                My.Computer.FileSystem.DeleteFile _
             ("C:\???file.txt")
            End If

            BackgroundWorker1.RunWorkerAsync()  ’DoWorkイベントへ移動

        End Sub

     '----------------------------------------------   
    Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
            On Error GoTo 999

            Dim file2mesh As String
            Dim nm As Integer, k As Integer, i As Integer, j As Integer
            Dim Yuka(64, 100, 100) As Integer
            Dim TotalYuka(255, 64) As Integer

            Dim MeshName(255, 64) As Integer


            For nm = 1 To nmD '1次メッシュ

         '操作終了状態かをチェックする。(ボタン6がクリックされたか)
          While Not BackgroundWorker1.CancellationPending = False
                     GoTo 998
                End While

                Url3 = CStr(counter(nm - 1))

                file2mesh = Dir(Url3 & "\*", FileAttribute.Normal)
                k = 0
                Do While file2mesh <> "" '2次メッシュ
                    k = k + 1
                    TotalYuka(nm, k) = 0

                    'ファイルを開かずに値を読み込む。

                    Using file3mesh As New Microsoft.VisualBasic.FileIO.TextFieldParser(Url3 & "\" & file2mesh)
                        file3mesh.TextFieldType = FileIO.FieldType.FixedWidth   '固定幅

                        Dim currentRow As String()
                        Dim currentField As String

                        file3mesh.SetFieldWidths(6) '一番上の行を読み取るため、幅を6に設定
                        currentRow = file3mesh.ReadFields '読み込み
                        MeshName(nm, k) = currentRow(0) 'メッシュの名前はカレント列の一番最初

                        'フォーマット変更
                        file3mesh.SetFieldWidths(10, 10, 10, 10, 10, 10, 10, 10, 10, 10, _
                                                  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, _
                                                  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, _
                                                  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, _
                                                  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, _
                                                  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, _
                                                  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, _
                                                  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, _
                                                  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, _
                                                  10, 10, 10, 10, 10, 10, 10, 10, 10, 10)


                        For i = 1 To 100
                             currentRow = file3mesh.ReadFields
                            j = 1

                            'カレント列内にあるカレントフィールドを導く
                            For Each currentField In currentRow
                                Yuka(k, i, j) = currentField
                                TotalYuka(nm, k) = TotalYuka(nm, k) + Yuka(k, i, j)
                                j = j + 1
                            Next
                         Next i

                      
                        My.Computer.FileSystem.WriteAllText _
                        ("C:\???file.txt", _
                          MeshName(nm, k) & "," & TotalYuka(nm, k) & vbCrLf, True)

                         End Using

                    file2mesh = Dir()

                Loop '2次メッシュ

                Dim PT = CInt(nm / nmD * 100)
                BackgroundWorker1.ReportProgress(PT)  ’ProgressChangedイベントに移動

            Next nm '1次メッシュ
    998:       e.Result = "CHECKが終了しました。"
    Exit Sub         ’RunWorkerCompletedイベントへ移動

    999:    MsgBox("error " & file2mesh)
            ProgressBar2.Visible = False
        End Sub
    '----------------------------------------------

        Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
            ProgressBar2.Value = e.ProgressPercentage
            Label5.Text = e.ProgressPercentage & "%完了"
        End Sub
    '----------------------------------------------
        Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
            ProgressBar2.Visible = False
            MsgBox(e.Result, MsgBoxStyle.OkOnly)
            Me.Enabled = True
        End Sub
    '----------------------------------------------
     Private Sub Button6_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button6.Click
            ProgressBar2.Visible = False
            Button6.Visible = False
            Button7.Enabled = True
            MsgBox("操作を終了しています。", MsgBoxStyle.OkOnly, "終了")
            Me.BackgroundWorker1.WorkerSupportsCancellation = True '操作終了を可能にする。
            Me.BackgroundWorker1.CancelAsync() '操作を中断し、DO_WORKに伝える。
        End Sub

    • 編集済み ワカRUN 2009年5月21日 7:34
    2009年5月15日 1:34