2010-04-08 10 views
5

Est-il sûr pour un thread de lire une variable définie par un événement Delphi VCL?Les threads peuvent-ils lire en toute sécurité les variables définies par les événements VCL?

Lorsqu'un utilisateur clique sur un TCheckbox VCL, le thread principal définit un booléen sur l'état Vérifié de la case à cocher.

CheckboxState := CheckBox1.Checked; 

A tout moment, un thread lit cette variable

if CheckBoxState then ... 

Peu importe si le fil "manque" une modification du booléen, car le thread vérifie la variable dans une boucle comme il fait d'autres choses. Donc, il verra l'état changer finalement ...

Est-ce sûr? Ou ai-je besoin de code spécial? Est-ce que la lecture et l'écriture de la variable (dans le thread et le thread principal respectivement) entourent les appels de code critique nécessaires et suffisants? Comme je l'ai dit, peu importe si le thread obtient la "mauvaise" valeur, mais je continue à penser qu'il pourrait y avoir un problème de bas niveau si un thread essaie de lire une variable pendant que le thread principal est en au milieu de l'écriture, ou vice versa.

Ma question est similaire à celle-ci: Cross thread reading of a variable who's value is not considered important.

(également lié à ma question précédente: Using EnterCriticalSection in Thread to update VCL label)

+0

Notez que les événements VCL ne sont pas vraiment spéciaux. Votre question s'applique tout aussi bien à l'accès à la variable à partir de n'importe quel * type * de fonction dans * n'importe quel * deux threads. –

Répondre

6

C'est sûr, pour trois raisons:

  • Un seul thread écrit à la variable. La variable est seulement un octet, donc il n'y a aucun moyen de lire une valeur incohérente. Il sera lu soit True soit False. Il ne peut pas y avoir de problèmes d'alignement avec les valeurs Delphi boolean.

  • Le compilateur Delphi ne vérifie pas si une variable est réellement écrite et n'optimise pas le code. Les variables non-locales seront toujours lues, le spécificateur volatile n'est pas nécessaire.

Cela dit, si vous êtes vraiment pas sûr de cela, vous pouvez utiliser une valeur integer au lieu du booléen, et utilisez la fonction InterlockedExchange() pour écrire à la variable. Ceci est exagéré ici, mais c'est une bonne technique à connaître, car pour les valeurs de taille de mot unique machine, il peut éliminer le besoin de verrous.

Vous pouvez également remplacer le boolean par une primitive de synchronisation appropriée, comme un événement, et avoir le bloc de thread sur cela - cela vous aiderait à éliminer les boucles occupées dans le thread.

1

Pour l'exemple que vous donnez, il sera en sécurité. Techniquement, le problème principal est dans les cas où votre variable dépasse un mot machine en taille, et ainsi vous pourriez obtenir le mot haut et le mot long non synchronisé. Pour les petites valeurs cependant, ce n'est pas un problème.

Si vous pensez qu'il s'agit d'un problème potentiel, par exemple en utilisant un pointeur, alors la chose à utiliser est une section TCritical pour contrôler la lecture et l'écriture sur l'élément. C'est assez rapide pour toutes les situations pratiques, et vous garantit une sécurité à 100%.

3

Dans votre cas (Propriété cochée), une opération de lecture est atomique, donc sécurisée. C'est la même chose qu'avec la propriété TThread.Terminated; les opérations simples de lecture et d'écriture pour les octets, mots et doubles mots correctement alignés sont atomiques. Vous pouvez vérifier intel documentation pour plus d'informations:

CHAPITRE 8 - GESTION multiprocesseur

8.1.1 garanti opérations atomiques

Le processeur Intel486 (et les nouveaux processeurs depuis) ​​garantit que les éléments suivants opérations de mémoire de base sera toujours effectué atomiquement:

  • lecture ou l'écriture d'un octet
  • lecture ou l'écriture d'un mot aligné sur une limite de 16 bits
  • lecture ou l'écriture d'un double mot aligné sur une limite de 32 bits

Le processeur Pentium (et les nouveaux processeurs depuis) ​​garantit que les opérations de mémoire supplémentaires suivantes seront toujours effectuées sur atomiquement:

  • lecture ou l'écriture d'un quadruple mot aligné sur une limite de 64 bits
  • 16-bit a accès à des emplacements de mémoire non mises en cache qui correspondent à un bus de données 32-bit
Questions connexes