web-dev-qa-db-fra.com

Que fait "DoEvents" dans vb6?

Que fait "DoEvents" dans vb6? Pourquoi est-ce que j'obtiens le message d'erreur "Out of stack space"? Qu'est-ce que ça veut dire ?

21
faressoft

DoEvents () permet de traiter d'autres messages Windows.

La raison pour laquelle vous obtenez une erreur d'espace de pile est probablement parce que DoEvents () permet à des événements de se produire qui appellent à nouveau votre code, qui appelle à nouveau DoEvents (), et ainsi de suite jusqu'à l'espace de pile, qui suit les adresses de retour pour tous ces appels, est épuisé.

En général, je ne recommande pas d'utiliser DoEvents () en raison de problèmes comme ceux-ci et du fait qu'il viole la conception événementielle globale de Windows.

18
Jonathan Wood

Une façon légèrement différente de voir DoEvents est de vider les événements dans la file d'attente d'événements. Si votre sous-fonction ou fonction déclenche un événement, ce gestionnaire d'événement devient un sous-programme en ligne pour s'exécuter dès que votre sous-fonction/fonction est terminée. DoEvents dit d'exécuter ce gestionnaire d'événements sous maintenant, au lieu d'attendre la fin de votre sous.

Bien que je sois d'accord avec Jonathon sur le fait de ne pas utiliser DoEvents, je tempérerais sa déclaration en disant que je ne recommande de l'utiliser que si vous savez exactement pourquoi, et connaissez toutes les répercussions du changement de l'ordre de la file d'attente des événements de cette façon. Le plus souvent, DoEvents est indiqué lorsque vous souhaitez mettre à jour votre écran d'une manière ou d'une autre dans le contexte d'un sous-programme, avant que le sous-programme ne soit terminé.

Un exemple de cela est lorsque vous utilisez le contrôle ProgressBar. Supposons que vous parcouriez plusieurs milliers d'enregistrements et que vous souhaitiez fournir à l'utilisateur des informations sur votre progression en mettant à jour une barre de progression. Vous pouvez interrompre votre boucle tous les cent enregistrements et modifier la valeur du contrôle de la barre de progression. Cependant (à moins que vous ne fassiez quelque chose), vous ne verrez la modification à l'écran qu'après l'exécution du gestionnaire d'événements de modification de la barre de progression, et ce gestionnaire ne s'exécutera pas tant que votre sous-marin n'aura pas terminé son exécution. Il sera simplement mis dans la file d'attente des événements. La façon de forcer l'événement change à s'exécuter immédiatement, en suspendant votre sous, consiste à appeler DoEvents. Cela videra tous les événements existants de la file d'attente - dans ce cas, l'événement de modification de votre barre de progression - et mettra à jour le contrôle de la barre de progression à l'écran.

Maintenant, "hors de l'espace de pile" signifie essentiellement que vous avez été pris dans une boucle sans fin d'appels de fonction. La façon la plus simple de provoquer cela est la suivante:

Public sub MySub()
    MySub
End Sub

Et puis appelez MySub quelque part. Vous obtiendrez une erreur d'espace de pile. Si vous regardez la pile d'appels, vous verrez une très longue ligne d'appels vers MySub.

Un exemple bien connu du monde réel se produirait dans les anciennes versions de VB:

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

Cette situation suppose deux membres d'un tableau de contrôles TextBox appelé TextBoxArray. Maintenant, si l'utilisateur commence par le premier (index 0) et passe au second (index 1), l'événement LostFocus de l'index 0 se déclenchera. Cependant, VB définirait également le focus en interne sur la zone d'index 1. Ensuite, le code redéfinirait le focus sur l'index 0, déclenchant l'événement LostFocus de l'index 1! Vous êtes pris dans une boucle. Ils ont corrigé cela dans VB5 ou 6 en attendant de définir le focus jusqu'à ce que l'événement LostFocus soit terminé en cours d'exécution.

6
BobRodes

Je clarifierais la réponse de Johnathon en ce qu'elle pompe cette boucle de message VB et permet au VB Runtime de traiter les messages Windows, ce qui est l'opposé de Sleep qui permet de Windows pour traiter ses événements (pas nécessaire dans le monde des processeurs multicœurs et des véritables systèmes d'exploitation multitâche, mais lorsque VB6 a été écrit, Windows 9x était le système d'exploitation dominant et une boucle dure qui ne contenait que des événements DoE augmenterait l'utilisation du processeur à 100%). voir des choses comme

While fDoneFile = False
    DoEvents
    Sleep 55
Wend

était un modèle courant dans le monde VB6.

5
Kris Erickson

Comme indiqué ailleurs, DoEvents autorise le déclenchement d'autres événements de votre application. Voici un exemple de la façon dont vous pouvez utiliser DoEvents sans le problème "Espace de pile insuffisant". Cela garantit que vous ne parcourez pas le code plusieurs fois en utilisant un booléen pour indiquer que le code est en cours d'exécution.

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