- - PR -
ループ処理で中断・再開するには
1|2|3
次のページへ»
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2008-04-11 01:17
お世話になります。
VB2005を使って、for nextのループを用いたプログラムを作っています。 そのループの中で、各回の処理(フォームの入力項目の自動入力など)の最後で一時中断をして、ボタンをクリックして再開させたいと思います。 中断〜再開の間には、該当フォームの入力項目を手作業で変更します。 その作業が終わったら、再開ボタンを押して、次のループ処理に移ります。 ここで質問です。 当初は、メッセージボックスを使って中断し、ボタンを押したら再開することを考えていましたが、メッセージボックスが表示されている間は、フォームにアクセスできません。 次に考えたのが、処理の中断を一定時間カウントさせるループ処理によりWait状態とし、再開ボタンがクリックするのを検知したら、waitループをexitするというものです。 プログラムの処理はこんな感じです。 Private sub main for i = 1 to 100 処理 call wait next End sub Private sub wait Do while 一定時間待つ If restart = True Then restart = False Exit Do End If Loop End sub Prive sub Button1_click restart = True End sub 上記のような処理で、一応、中断〜再開はできるようになったのですが、どうもメインプログラムの動作が不安定です。 具体的には、フォームの入力項目の自動入力処理が、たまにうまくいかないことがあるのです。 中断〜再開処理を削除し、ループ処理だけにすると処理は正常に行われるので、中断〜再開処理に問題があるものと推測しています。 そもそも、ループ処理の中断〜再開を行う方法として、上記のような方法が良いのかも自信がありません。 ループ処理の中断〜再開には、本来どのような処理をすればよいのかご指導いただきたく思います。 よろしくお願いします。 | ||||||||
|
投稿日時: 2008-04-11 09:31
こんにちは。
動作が不安定になるのは、Do〜Loopをまわし続けているからです。 Do〜Loop中はApplication.DoEvents()を入れてもCPU使用率が100%になってしまいます。(タスクマネージャで確認) 精査は必要ですが、以下のものである程度望まれているものができると思います。
| ||||||||
|
投稿日時: 2008-04-11 10:09
自動入力で中断・再開・・・ちょっとやりたいことが理解できませんでしたので、
外していたらすみません。 バックグラウンドで処理させたいのであれば、マルチスレッドにした方がよいと思います。 VB2005以降なら BackgroundWorker で比較的簡単に実装できます。 参考URL http://www.atmarkit.co.jp/fdotnet/dotnettips/436bgworker/bgworker.html | ||||||||
|
投稿日時: 2008-04-11 15:22
nakaPさん、こんにちは
コードをご提示くださってありがとうございます。 おかげさまで、一時停止〜再開のロジックはよくわかりました。 早速テストしたところ、StopButtonをクリックしても、pauseできないことがあります。 何度かクリックすれできるんですが。 そういえば、私が示したコードでも、Button1(再開ボタン)を押しても再開できないことがたまにあったことと同様な現象ではないかと思いました。 waitに入ったとき、ボタンがクリックされたことを確実に判断するためのヒントをお示しいただけないでしょうか。 あと、「Do〜Loop中はApplication.DoEvents()を入れてもCPU使用率が100%になってしまいます」とのことですが、確かにそうなりました。以前どこかでみかけたのですが、それを防止するためには、System.Threading.Thread.Sleepを加えればよいとのことでした。 | ||||||||
|
投稿日時: 2008-04-11 15:33
テッテさん、こんにちは
ご回答ありがとうございます。 >自動入力で中断・再開・・・ちょっとやりたいことが理解できませんでしたので、 フォームの入力項目に自動入力をしていくのですが、自動入力処理の後、念のため、人手によるチェックを行い、必要に応じて修正を加えたいのです。そのため、自動入力処理が終わったら、いったん処理を中断させ、人手によるチェック・修正が完了したら、再開、すなわち、次のfor next処理に移りたい、というものです。 >バックグラウンドで処理させたいのであれば、マルチスレッドにした方がよいと思います。 上記のような中断〜再開処理の場合、どの処理をバックグランドにもっていけばよいのか、よくわかりません。 具体的に教えていただけませんでしょうか。 よろしくお願いします。 | ||||||||
|
投稿日時: 2008-04-11 16:22
よくわかりました。
やはりマルチスレッドにしたほうが安定すると思います。 そうすれば、CPU使用率が上がることも、ボタンがときどき反応しないようなこともなくなります。 この場合は、for ループを丸ごと BackgroundWorker で実行すればよいと思います。 ただし、フォーム上のコントロールへのアクセスは Invoke を使わなければならないので、 少々面倒にはなりますが。 使い方は先ほどのURLを参考にしてください。 | ||||||||
|
投稿日時: 2008-04-11 16:46
ループ部分を分解することをオススメします。 Win32やWindows.Formsのメッセージング・イベントは 長期間処理をすることを前提に作られていません。 自前のループの中でWindowsのメッセージポンプに処理をもどす、 つまりループでApplication.DoEventsを行うと さまざまな部分で不具合が生じます。 #顕著なのはフォームを閉じたときでしょうか。 ループを分解し、 ループカウンタを使うなどしてループの状態をフォームに記憶させ、 タイマーやApplication.Idleで処理をするといいでしょう。 このようにするとスレッドを使ったり、細かいところに気を使わなくても、 うまく動きます。 ボタンがうまく押せなかったり、 CPU利用率が100%になってしまったり、 フォーカスがうまく動かなかったり、 メッセージボックスが表示されなかったり、 閉じるボタンをおしたらエラーになったり、 そういった問題を全て避けることができます。 コルーチンを自分で実装しろ、ということですね。 | ||||||||
|
投稿日時: 2008-04-11 18:04
コルーチンという言葉を初めて聞いたので、少し惹かれて作ってみました。
こういうことなのかな? 確かに、Application.DoEvents()を使うよりも安定しているかも。 |
1|2|3
次のページへ»