web-dev-qa-db-ja.com

「DoEvents」はvb6で何をしますか?

「DoEvents」はvb6で何をしますか? 「スタック領域が足りません」というエラーメッセージが表示されるのはなぜですか?どういう意味ですか ?

21
faressoft

DoEvents()を使用すると、他のWindowsメッセージを処理できます。

スタックスペース不足エラーが発生する理由は、DoEvents()が、コードを再度呼び出すイベントの発生を許可しているためです。これにより、DoEvents()が再度呼び出され、スタックスペースまで、これらすべての戻りアドレスを追跡します。呼び出し、不足しています。

一般に、このような問題と、Windowsのイベント駆動型デザイン全体に違反するという事実のため、DoEvents()の使用はお勧めしません。

18
Jonathan Wood

DoEventsを見る少し異なる方法は、イベントキュー内のイベントをフラッシュすることです。サブルーチンまたは関数がイベントをトリガーすると、そのイベントハンドラーはサブルーチンになり、サブ/関数が終了するとすぐに実行されるようになります。 DoEventsは、あなたのサブルーチンの終わりまで待つのではなく、今すぐそのイベントハンドラーサブルーチンを実行するように言います。

DoEventsを使用しないことについてJonathonと精神的に同意しますが、正確に理由がわかっていて、イベントキューの順序をこのように変更した場合のすべての影響を知っている場合にのみ使用することをお勧めします。ほとんどの場合、サブルーチンの実行が完了する前に、サブルーチンのコンテキスト内から何らかの方法で画面を更新するときに、DoEventsが示されます。

この例は、ProgressBarコントロールを使用している場合です。数千のレコードを反復処理していて、進行状況バーを更新することにより、現在の進捗状況をユーザーにフィードバックしたいとします。 100レコードごとにループを中断し、プログレスバーコントロールの値を変更する場合があります。ただし、(それについて何かを行わない限り)プログレスバーの変更イベントハンドラーが実行されるまで画面に変更は表示されず、そのハンドラーはサブルーチンの実行が完了するまで実行されません。イベントキューに入れられるだけです。変更イベントを強制的に実行してサブルーチンを一時停止するには、DoEventsを呼び出します。これにより、キューから既存のすべてのイベント(この場合はプログレスバーの変更イベント)がフラッシュされ、画面上のプログレスバーコントロールが更新されます。

ここで、「スタックスペースが足りない」とは、基本的に、関数呼び出しの無限ループに巻き込まれたことを意味します。それを引き起こす最も基本的な方法はこれです:

Public sub MySub()
    MySub
End Sub

そして、どこかからMySubを呼び出します。スタックスペース不足エラーが発生します。呼び出しスタックを見ると、MySubへの非常に長い呼び出し行が表示されます。

これのよく知られた実例は、古いバージョンのVBで発生します。

Public Sub TextBoxArray_LostFocus(index as Integer)
    If TextBoxArray(index) = "" Then
        TextBoxArray(index).SetFocus
        MsgBox "Please enter a value"
    End If
End Sub

この状況は、TextBoxArrayと呼ばれるTextBoxコントロール配列の2つのメンバーを想定しています。ここで、ユーザーが最初のインデックス(インデックス0)から開始して2番目のインデックス(インデックス1)に移動すると、インデックス0のLostFocusイベントが発生します。ただし、VBは、内部的にフォーカスをインデックス1ボックスに設定します。その後、コードはフォーカスをインデックス0に戻し、インデックス1のLostFocusイベントを発生させます!ループに巻き込まれます。 LostFocusイベントの実行が完了するまでフォーカスを設定するのを待つことで、VB5または6で修正されました。

6
BobRodes

VBメッセージループをポンプし、VBランタイムがWindowsメッセージを処理することをランタイムに許可します。これは、スリープを可能にするスリープの反対です。イベントを処理するためのWindows(マルチコアCPUや真のマルチタスクOSの世界では必要ありませんが、VB6が作成されたとき、Windows 9xが支配的なOSであり、DoEventsのみが含まれるハードループがCPU使用率を100%に急上昇させました)。のようなものを見て

While fDoneFile = False
    DoEvents
    Sleep 55
Wend

vB6の世界では一般的なパターンでした。

5
Kris Erickson

他の場所で述べたように、DoEventsを使用すると、アプリケーション内の他のイベントを発生させることができます。 「スタック領域不足」の問題なしにDoEventsを使用する方法の例を次に示します。これにより、ブール値を使用してコードが実行されていることを示すことにより、コードを何度も実行する必要がなくなります。

Sub Example()
    'Create static variable to indicate the sub is running.
    Static isRunning As Boolean
    'Exit the sub if isRunning
    If isRunning Then Exit Sub
    'Indicate sub is running
    isRunning = True
    'Sub does stuff
    DoEvents
    'Ends up calling sub again
    Example 'Added just to prove via testing.
    'Indicate sub is no longer runningrunning
    isRunning = False
End Sub
4
Daniel