• ベストアンサー

終了してもプログラムが実行したまま(VB)

非常に時間のかかる繰り返し処理を行なうプログラムを作りました。どのくらい、プログラムが進行しているのかわかりやすくするため、 Progress.Show でProgressという名前のフォームを表示し、そこに、プログラムが何%終わったのか表示するようにしました。 プログラムはDo Loop文が使ってあるので、何%終わったのかを表示するためにLoopした回数を取得して、それをフォームに表示することにしましたが、どこかで調べたら機械は、Do Loopのあいだはフォーム上に文字を表示するのに手が回らないからDoEventsを使ってイベントを実行させなさい、といわれました。 そこまではうまくいきました。プログラムを実行すると、プログラムが実行されて何%終わったかもちゃんと表示できるようになりました。 ところが、プログラムの実行中にフォームの右上の×ボタンを押したところ、フォームは画面から消え、プログラムが終了したように見えるのに、VB Editorでは[実行中]となっており、終わってくれません。ずっとDo Loopが実行されたままです。 Private Sub Form_Terminate() のところに Unload Progress と書いても、「Unloadメソッドは使えません」などというエラー・メッセージが出ます。(フォーム上にボタンを置き、そこをクリックするとUnloadするようにしてみましたがやはり同じことを言われました。) 原因は何でしょうか? フォームをUnloadする、ということの意味をちゃんと理解していないのでいけないのだと思うのですが、調べてもよく言っていることがわかりません。 よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • piyo2000
  • ベストアンサー率49% (144/293)
回答No.4

>いったんLoopに入ったら、中断させる方法がない、ということでしょうか。 Exit Doで抜けられますが・・・(^^; というより、この場合無限Loopは使うべきじゃないですね。 #2さんが言われるようにキャンセルボタンを置いて キャンセルボタンではキャンセルフラグをON(TRUE)にします。(キャンセルフラグはモジュール変数) Do While (キャンセルフラグ=FALSE and 100%じゃない ) 表示処理 DoEvents Loop のようにします。 # Untilを使うと分かりやすいですがあえてWhileで。 >Timerをつかうと、途中で中断できるのでしょうか。 考え方は上記と一緒です。 Timerイベントでキャンセルボタンが押されたかどうかをチェックすればいいだけです。 #1さんが(描画にも)Timerを使ったほうがいい、というのはタスクマネージャでCPU使用率を表示させてみると分かると思います(^^; また、この原因はDoEventsを使っているから、なんですけどね(^^; DoEventsを使うと、時間が掛かる処理中にも別のイベントが発生(この場合はUnload)するからで、なおかつLoopを抜けていないからですね。 Do Whileを使うなら、UnloadイベントにもキャンセルフラグをONにするコードを書けばループを抜けてくれるので終わってくれるはずです。 #3さんの「Endを使えば」というのは手っ取り早く確実な方法ですが、個人的には使うべきじゃないと思います(^^; このケースでは関係ないですが、オブジェクトの寿命に無頓着になりがちだからです。

crooked_man
質問者

補足

BLUEPIXYさん、kahaさん、piyo2000さん、ありがとうございます。 いろいろと教えていただきましたが、僕は重大な勘違いをしていました。Unloadというのは、「全部やめなさい」という意味だと思っていたのです。ですからUnloadを書いた時点で何もかも終わるはずだと思っていたのです。 ところがpiyo2000さんのお答えの中で、UnloadイベントにフラグをOnするコードをかけば、、、というのがありました。Unloadしたら全部終わるのだからUnload後にコードを書いても無駄では?と思ったのですが、Unloadはそういうことではないのですね?? >Do While (キャンセルフラグ=FALSE and 100%じゃな >い ) >表示処理 >DoEvents >Loop >のようにします。 たいへんわかりやすいです。思いつきませんでした。ということは、UnloadしたときにキャンセルフラグをTrueにするようにしてもいいということですね。

その他の回答 (3)

  • kaha
  • ベストアンサー率23% (41/177)
回答No.3

> Unload Progress > と書いても、「Unloadメソッドは使えません」 Progress.Showと呼び出し元が先に終了してしまっているからではないでしょうか? 呼び出し元で×ボタンで終了直前に呼ばれるQueryUnloadイベントの処理にステートメントの End を実行するよいうにすればどうでしょうか?

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.2

>ユーザがいやになったら中断できるようにしたい Progressフォームにキャンセルボタンを置いて 押されたら中断するようにすればいいでしょう また、×ボタンを押したら、キャンセルボタンクリックイベントを実行するようにしておけばより良いと思います。

  • todo36
  • ベストアンサー率58% (728/1234)
回答No.1

>原因は何でしょうか? プロセスが動いたままだから。 >ずっとDo Loopが実行されたままです。 これです。 Loopから抜けなければプロセスは終わりません。 >Do Loopのあいだはフォーム上に文字を表示するのに手が回らないからDoEventsを使ってイベントを実行させなさい、といわれました DoEventsだけでは重いのでSleepも入れた方がいいでしょう。 いや、Loopで回すのではなくTimerを使うのがよいと思います。

crooked_man
質問者

補足

ありがとうございます。 ということは、いったんLoopに入ったら、中断させる方法がない、ということでしょうか。 また、Timerをつかうと、途中で中断できるのでしょうか。かなり時間のかかる処理なので、ユーザがいやになったら中断できるようにしたいと思っています。

関連するQ&A