プロが教えるわが家の防犯対策術!

非常に時間のかかる繰り返し処理を行なうプログラムを作りました。どのくらい、プログラムが進行しているのかわかりやすくするため、

Progress.Show

でProgressという名前のフォームを表示し、そこに、プログラムが何%終わったのか表示するようにしました。

プログラムはDo Loop文が使ってあるので、何%終わったのかを表示するためにLoopした回数を取得して、それをフォームに表示することにしましたが、どこかで調べたら機械は、Do Loopのあいだはフォーム上に文字を表示するのに手が回らないからDoEventsを使ってイベントを実行させなさい、といわれました。

そこまではうまくいきました。プログラムを実行すると、プログラムが実行されて何%終わったかもちゃんと表示できるようになりました。

ところが、プログラムの実行中にフォームの右上の×ボタンを押したところ、フォームは画面から消え、プログラムが終了したように見えるのに、VB Editorでは[実行中]となっており、終わってくれません。ずっとDo Loopが実行されたままです。

Private Sub Form_Terminate()
のところに

Unload Progress

と書いても、「Unloadメソッドは使えません」などというエラー・メッセージが出ます。(フォーム上にボタンを置き、そこをクリックするとUnloadするようにしてみましたがやはり同じことを言われました。)

原因は何でしょうか?
フォームをUnloadする、ということの意味をちゃんと理解していないのでいけないのだと思うのですが、調べてもよく言っていることがわかりません。
よろしくお願いします。

A 回答 (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を使えば」というのは手っ取り早く確実な方法ですが、個人的には使うべきじゃないと思います(^^;
このケースでは関係ないですが、オブジェクトの寿命に無頓着になりがちだからです。

この回答への補足

BLUEPIXYさん、kahaさん、piyo2000さん、ありがとうございます。

いろいろと教えていただきましたが、僕は重大な勘違いをしていました。Unloadというのは、「全部やめなさい」という意味だと思っていたのです。ですからUnloadを書いた時点で何もかも終わるはずだと思っていたのです。
ところがpiyo2000さんのお答えの中で、UnloadイベントにフラグをOnするコードをかけば、、、というのがありました。Unloadしたら全部終わるのだからUnload後にコードを書いても無駄では?と思ったのですが、Unloadはそういうことではないのですね??

>Do While (キャンセルフラグ=FALSE and 100%じゃな
>い )
>表示処理
>DoEvents
>Loop
>のようにします。

たいへんわかりやすいです。思いつきませんでした。ということは、UnloadしたときにキャンセルフラグをTrueにするようにしてもいいということですね。

補足日時:2004/12/25 19:43
    • good
    • 0

> Unload Progress


> と書いても、「Unloadメソッドは使えません」

Progress.Showと呼び出し元が先に終了してしまっているからではないでしょうか?

呼び出し元で×ボタンで終了直前に呼ばれるQueryUnloadイベントの処理にステートメントの End を実行するよいうにすればどうでしょうか?
    • good
    • 0

>ユーザがいやになったら中断できるようにしたい


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

>原因は何でしょうか?



プロセスが動いたままだから。

>ずっとDo Loopが実行されたままです。

これです。
Loopから抜けなければプロセスは終わりません。

>Do Loopのあいだはフォーム上に文字を表示するのに手が回らないからDoEventsを使ってイベントを実行させなさい、といわれました

DoEventsだけでは重いのでSleepも入れた方がいいでしょう。

いや、Loopで回すのではなくTimerを使うのがよいと思います。

この回答への補足

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

補足日時:2004/12/24 17:55
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています