Voici une énigme pour vous. J'ai un programme multithread dans lequel certains threads travaillent avec des ressources gérées comme des verrous et des sémaphores. Certaines primitives de libération de verrous ne peuvent être exécutées qu'à partir du même thread sur lequel l'acquisition du verrou a été faite.
Voici donc mon énigme : j'enveloppe ce type d'opérations : try { lock-acquire... do something } finally { lock-release }, mais parfois, lorsque mes threads se terminent, les clauses finally sont exécutées par le thread de collecte des ordures .NET et non par mon thread. (Le cas spécifique implique en fait le Dispose d'un objet alloué dans une instruction "using" ; voir ci-dessous pour plus de détails).
C'est un peu délicat à démontrer ; je vois cela tout le temps dans Isis2, et j'ai compris que cela se produisait en vérifiant les identifiants des threads dans les blocs acquire et finalize. Mais je n'ai pas de démo en 3 lignes pour vous, et j'en suis désolé. Je sais qu'il serait plus facile de vous aider.
Existe-t-il un moyen de retarder la fin d'un thread jusqu'à ce que tous les blocs de finalisation en attente associés à ce thread aient été exécutés ?
---- Détails ajoutés pour Mark ----
Ce que je suis en train de faire implique un paquetage de verrouillage auto-instrumenté assez élaboré qui a diverses abstractions de verrouillage (bounded buffers, barriers, normal locks, etc.) avec des priorités de threads et conçu pour auto-détecter les blocages, les inversions de priorité, les octrois de verrou très lents et d'autres problèmes. Mon code est suffisamment complexe et threadé pour que j'en aie besoin pour le déboguer.
Voici un exemple de mon style de construction de base :
LockObject myLock = new LockObject("AnIsis2Lock");
...
using(new LockAndElevate(myLock)) { stuff }
Un LockObject est un verrou à contrôle automatique... un LockAndElevate note que je l'ai verrouillé (dans ce cas) et suit plus tard le dispose, lorsque je le déverrouille. J'exploite donc le fait que l'utilisation devrait se débarrasser du nouvel objet lorsque le bloc se termine -- même s'il lance une exception.
Ce que je constate, c'est qu'assez souvent, les threads se terminent alors que les événements using dispose n'ont pas encore eu lieu ; ils s'exécutent plus tard, sur un autre thread. Cela ne se produit que lorsque l'un de mes threads se termine ; en exécution normale, tout fonctionne comme un charme.
Donc, puisque l'utilisation traduit try... finally, ma question a été posée en termes de clauses finales.