Question

J'ai écrit un composant com dans .NET et si j'essaie de verrouiller un objet dans une méthode (invoquée par un code non managé qui parle à mon composant com), j'obtiens une exception.

Je n'ai pas le texte exact de l'exception pour le moment, mais ce n'était pas très utile non plus.

Ma question est donc de savoir dans quelles circonstances un verrou (syncObject) lève une exception? Voici quelques faits:

  • syncObject n'est pas null
  • syncObject n'est pas déjà verrouillé

Cela aurait-il quelque chose à voir avec l'appelé qui courait dans un appartement à filetage unique (STA) ou un appartement à filetage multiple (MTA)?

Était-ce utile?

La solution

De cette page :

  

Chaque acquisition de verrou peut générer une exception. Soyez prêt pour cela.

     

La plupart des verrous allouent paresseusement un événement si une acquisition de verrous rencontre un conflit, y compris les moniteurs CLR. Cette affectation peut échouer lorsque les ressources sont insuffisantes, ce qui entraîne des MOO provenant de l'entrée de l'écluse. (Notez qu'un verrou de verrouillage type non bloquant typique ne peut pas échouer avec le MOO, ce qui lui permet d'être utilisé dans certains scénarios à ressources limitées, comme dans un CER.) De même, un hôte tel que SQL Server peut effectuer une détection d'interblocage et même briser ces blocages en: générer des exceptions issues de l'instruction Enter, se présentant sous la forme d'une exception System.Runtime.InteropServices.COM.

     

Souvent, il n’ya pas grand chose à faire pour répondre à une telle exception. Cependant, les codes sensibles à la fiabilité et à la sécurité qui doivent faire face aux défaillances doivent prendre en compte ce cas. Nous aurions aimé pouvoir répondre intelligemment aux blocages d’hôtes, mais la plupart des codes de bibliothèque ne peuvent pas être résolus intelligemment à un point sûr de la pile afin de pouvoir revenir en arrière et relancer l’opération. Il y a simplement trop de mélange inter-bibliothèques sur une pile typique. C'est pourquoi les acquisitions de Monitor basées sur un délai d'expiration avec TryEnter sont généralement une mauvaise idée pour la prévention des blocages.

Comme vous pouvez le lire, il semble que, dans des conditions de ressources limitées, des exceptions soient générées par la méthode Enter de Monitor que lock (o) utilise en interne.

Alors, peut-être que votre solution ressemble à une attente en attente?

{
    uint iters = 0;
    while (!cond) {
        if ((++iters % 50) == 0) {
            // Every so often we sleep with a 1ms timeout (see #30 for justification).
            Thread.Sleep(1);
        } else if (Environment.ProcessorCount == 1) {
            // On a single-CPU machine we yield the thread.
            Thread.Sleep(0);
        } else {
            // Issue YIELD instructions to let the other hardware thread move.
            Thread.SpinWait(25);
        }
    }
}

Où cond pourrait être un peu

private volatile int cond = 0

utilisé avec par exemple Interlocked.CompareExchange où vous passez, par exemple, à Thread.Current.ManagedThreadID ou autre chose non nulle?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top