"DoEvents" は vb6 で何をしますか? 「スタック領域が不足しています」というエラー メッセージが表示されるのはなぜですか? どういう意味ですか ?
4 に答える
DoEvents() を使用すると、他の Windows メッセージを処理できます。
スタック スペース不足エラーが発生する理由は、おそらく DoEvents() が、コードを再度呼び出すイベントの発生を許可しているためです。これにより、DoEvents() が再び呼び出され、これらすべての戻りアドレスを追跡するスタック スペースまで続きます。コール、使い果たしました。
一般に、DoEvents() の使用はお勧めしません。このような問題と、Windows の全体的なイベント ドリブン設計に違反しているという事実のためです。
DoEvents の少し異なる見方は、イベント キュー内のイベントをフラッシュすることです。サブまたは関数がイベントをトリガーする場合、そのイベント ハンドラーは、サブ/関数が終了するとすぐに実行されるサブになります。DoEvents は、サブルーチンの最後まで待つのではなく、そのイベント ハンドラー サブルーチンを今すぐ実行するように指示します。
DoEvents を使用しないことについては Jonathon の意見に同意しますが、DoEvents を使用することをお勧めするのは、その理由が正確にわかっていて、この方法でイベント キューの順序を変更した場合のすべての影響を知っている場合に限ると述べて、彼の発言を和らげたいと思います。ほとんどの場合、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 でそれを修正しました。
そのVBメッセージループをポンプし、VBランタイムがWindowsメッセージを処理できるようにするというJohnathonの答えを明確にします。これは、Windowsがイベントを処理できるようにするスリープの反対です(マルチコアCPUと真のマルチタスクOSの世界では必要ありませんしかし、VB6 が作成されたときは、Windows 9x が支配的な OS であり、DoEvents のみを含むハード ループは CPU 使用率を 100% に急上昇させました)。だから、次のようなものを見る
While fDoneFile = False
DoEvents
Sleep 55
Wend
VB6 の世界全体で共通のパターンでした。
他の場所で述べたように、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