web-dev-qa-db-fra.com

Sécurité des threads de System.Timers.Timer vs System.Threading.Timer

Dans cet article: http://msdn.Microsoft.com/en-us/magazine/cc164015.aspx l'auteur déclare que System.Threading.Timer n'est pas thread-safe .

Depuis lors, cela a été répété sur les blogs, dans le livre de Richter "CLR via C #", sur SO, mais cela n'est jamais justifié.

De plus, la documentation MSDN assure "Ce type est thread-safe".

1) Qui dit la vérité?

2) S'il s'agit de l'article d'origine, ce qui rend System.Threading.Timer non thread-safe et comment son wrapper System.Timers.Timer permet une plus grande sécurité des threads?

Merci

23
Pragmateek

Non, ce n'est pas comme ça que ça fonctionne. Les classes Timer asynchrones .NET sont parfaitement thread-safe. Le problème avec la sécurité des threads est que ce n'est pas une propriété transitive, cela ne rend pas non plus le code autre qui est exécuté thread-safe. Le code que vous avez écrit, pas un programmeur .NET Framework.

C'est le même type de problème avec l'hypothèse très courante que le code de l'interface utilisateur Windows est fondamentalement non sûr pour les threads. Ce n'est pas le cas, le code à l'intérieur de Windows est parfaitement thread-safe. Le problème est tout le code qui s'exécute qui est pas une partie de Windows et non écrit par un programmeur Microsoft. Il y a toujours un lot de ce code, déclenché par un appel SendMessage (). Qui exécute du code personnalisé écrit par un programmeur. Ou du code qu'il n'a pas écrit, comme un crochet installé par un utilitaire. Code qui suppose que le programme ne le rend pas difficile et exécute simplement des gestionnaires de messages sur un thread. Il le fait généralement, ne pas le faire lui achète un beaucoup de problèmes.

Même problème avec l'événement System.Timers.Timer.Elapsed et le rappel System.Threading.Timer. Les programmeurs font beaucoup d'erreurs lors de l'écriture de ce code. Il s'exécute de manière asynchrone complète sur un thread de pool de threads arbitraire, toucher une variable partagée nécessite vraiment un verrouillage pour protéger l'état. Très facile à ignorer. Et pire, bien pire, très facile de vous mettre dans une pile de problèmes lorsque le code s'exécute encore, avant que l'invocation précédente ne s'arrête. Déclenché lorsque l'intervalle de la minuterie est trop faible ou que la machine est trop chargée. Maintenant, il y a deux threads exécutant le même code, qui arrivent rarement à une bonne fin.

L'enfilage est difficile, nouvelles à onze heures.

46
Hans Passant