Enveloppez un objet AutoResetEvent dans un WaitHandle restreint?
-
26-10-2019 - |
Question
Je l'ai construit une bibliothèque qui lance un fil pour le faire de chose et retourne un WaitHandle à l'appelant.
Regarder un rapport de bogue, je soupçonne que le code qui vous appelle ma bibliothèque prend l'objet retourné et le jetant à un AutoResetEvent (ce qui est) et d'élever le drapeau lui-même. Il n'est pas censé le faire.
Y at-il une manière que je peux envelopper l'objet AutoResetEvent avec celui qui peut encore être WaitOne'd et WaitAny'd, mais ne peut être soulevée par mon code?
Merci.
La solution
Vous pouvez créer une nouvelle classe dérivée de EventWaitHandle
et override Set
et Reset
ils ne font rien, ou jeter une exception. En fait, vous devez créer des implémentations de new
, puisque Set
et Reset
ne sont pas virtuelles. Bien sûr, vous auriez à créer vos propres méthodes, d'autres nom. Comme MyInternalSet
et MyInternalReset
. Possible, mais je ne recommanderais pas le faire.
Au lieu de cela, je documenterait que le client ne doit pas activer ou désactiver l'événement, car cela entraînera un comportement imprévisible.
Vous pouvez créer une classe dérivée WaitHandle
qui tient votre AutoResetEvent
comme une propriété de internal
. Le code client alors ne serait pas en mesure d'y accéder. Quelque chose comme:
public class MyWaitHandle: WaitHandle
{
internal AutoResetEvent InternalEvent { get; private set; }
internal MyWaitHandle(AutoResetEvent event)
{
InternalEvent = event;
}
public override bool WaitOne(int32 timeout)
{
return InternalEvent.WaitOne();
}
}
Vous devrez remplacer la méthode de Dispose(Boolean)
protégée, afin qu'il disposera la poignée intérieure, et vous voulez que les autres surcharges WaitOne
, aussi bien. Vous pouvez ensuite créer des implémentations internal
de Set
et Reset
, ou tout simplement avoir votre code appel InternalHandle.Set
.
Je pense toujours le meilleur plan d'action est de dire au client de ne pas le faire. Mais si vous devez l'empêcher, le travail devrait ci-dessus.