トップ回答者
実行中の動作

質問
回答
-
プログラム実行中に、formを動かしてしまうと作業がストップしてしまうので困っています。
Windowsで動くアプリケーションというのは、一定時間毎に画面を更新したり、マウスの移動イベントを受け取ったり、キーボードの入力を受け取ったりという、"様々な処理"をする必要があります。
(タスクマネージャで応答なしの状態)
今回、「大量ファイルの数値データを読み込む」といった非常に時間のかかる処理を書かれていますので、前述のような"様々な処理"がずっと順番待ちのままになります。
この順番待ちの状態が長く続いていると、Windows XP以降のOSでは真っ白のウィンドウになったり、応答なしと表示されます。
よくある解決策としては、長くかかる処理を別スレッドで実行する方法(前者)と、処理を分割してタイマーイベントで続きをする方法(後者)ですね。
本質的には前者で解決するべきです。
前者は"様々な処理"と同時に時間のかかる処理を並行させる方法です。
BackgroundWorkerというキーワードが出ていますので、それについて調べてみて下さい。
後者はちょっと処理をしては、"様々な処理"をさせる余裕を与えて、またちょっと処理するということを繰り返します。
例えば、100個の処理があるとしたら、5個実行して抜けて、1秒ごとのTimer_Tickが来たら次の5個を処理することを繰り返して、"様々な処理"を実行する余裕を与えてあげるやり方です。
いずれにしても、スレッドやタイマーといった仕組みを知っていないと、意図せぬ動きをするプログラムになることがあります。
何らかの書籍を購入して勉強される等、体系的に学べるようにしましょう。
解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。- 回答としてマーク ワカRUN 2009年5月15日 1:07
すべての返信
-
プログラム実行中に、formを動かしてしまうと作業がストップしてしまうので困っています。
Windowsで動くアプリケーションというのは、一定時間毎に画面を更新したり、マウスの移動イベントを受け取ったり、キーボードの入力を受け取ったりという、"様々な処理"をする必要があります。
(タスクマネージャで応答なしの状態)
今回、「大量ファイルの数値データを読み込む」といった非常に時間のかかる処理を書かれていますので、前述のような"様々な処理"がずっと順番待ちのままになります。
この順番待ちの状態が長く続いていると、Windows XP以降のOSでは真っ白のウィンドウになったり、応答なしと表示されます。
よくある解決策としては、長くかかる処理を別スレッドで実行する方法(前者)と、処理を分割してタイマーイベントで続きをする方法(後者)ですね。
本質的には前者で解決するべきです。
前者は"様々な処理"と同時に時間のかかる処理を並行させる方法です。
BackgroundWorkerというキーワードが出ていますので、それについて調べてみて下さい。
後者はちょっと処理をしては、"様々な処理"をさせる余裕を与えて、またちょっと処理するということを繰り返します。
例えば、100個の処理があるとしたら、5個実行して抜けて、1秒ごとのTimer_Tickが来たら次の5個を処理することを繰り返して、"様々な処理"を実行する余裕を与えてあげるやり方です。
いずれにしても、スレッドやタイマーといった仕組みを知っていないと、意図せぬ動きをするプログラムになることがあります。
何らかの書籍を購入して勉強される等、体系的に学べるようにしましょう。
解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。- 回答としてマーク ワカRUN 2009年5月15日 1:07
-
キャンセルボタンの使い方を追加しました。
参考にどうぞ。
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.Textcounter = My.Computer.FileSystem.GetDirectories(Url & "H12世界測地系")
nmD = counter.Count
Else RadioButton5.Checked = True Then
Url2 = Url & "H12日本測地系\"
Label4.Text = RadioButton5.Textcounter = 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 IfBackgroundWorker1.RunWorkerAsync() ’DoWorkイベントへ移動
End Sub
'----------------------------------------------
Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
On Error GoTo 999Dim 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 IntegerDim MeshName(255, 64) As Integer
For nm = 1 To nmD '1次メッシュ
'操作終了状態かをチェックする。(ボタン6がクリックされたか)
While Not BackgroundWorker1.CancellationPending = False
GoTo 998
End WhileUrl3 = 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 Stringfile3mesh.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