web-dev-qa-db-fra.com

InvalidOperationException dans ma fabrique de valeurs Lazy <>

J'ai une classe contenant quelque chose comme ceci:

public static class Config
{
    private static Lazy<ConfigSource> _cfgSrc = new Lazy<ConfigSource>(
        () => { /* "ValueFactory" here... */ },
        true);

    public static ConfigSource ConfigSource
    {
        get { return _cfgSrc.Value; }
    }
}

En accédant à la propriété ConfigSource, j'ai rencontré ce InvalidOperationException:

ValueFactory a tenté d'accéder à la propriété Value de cette instance.

Je ne vois rien dans ma méthode "value factory" qui accède à la propriété Value. Y a-t-il autre chose qui pourrait déclencher cette exception? Ce problème ne se produit que par intermittence, mais une fois qu'il le fait, il faut réinitialiser IIS pour effacer l'exception (qui semble être mis en cache une fois qu'elle se produit).

38
Jacob

Il s'est avéré que cette erreur ne s'est produite qu'en essayant d'inspecter la propriété Value de Lazy<> dans le débogueur Visual Studio. Cela semblait créer un blocage car l'accès à Value semblait alors bloquer le thread pendant une longue période jusqu'à ce que InvalidOperationException se soit finalement produit. Je n'ai jamais pu intercepter l'original Exception, donc je n'ai pas pu voir la trace de pile interne.

Je note cela comme un bogue dans Visual Studio ou leur implémentation de Lazy<>.

34
Jacob

ValueFactory a tenté d'accéder à la propriété Value de cette instance.

Cela peut aider quelqu'un, j'ai pu corriger cette erreur en inspectant toute ma procédure ValueFactory. Dans mon exemple, je créais un modèle simple et le liais avec d'autres données mais pendant le processus de liaison, j'accédais à la propriété Value dans un singleton et cela a provoqué l'erreur.

Donc accéder à la valeur d'un objet Lazy à l'intérieur des lancements ValueFactory tel ne erreur. Comme le message d'erreur l'indique déjà ;-)

14
Viktor Hofer

Cela m'est également arrivé avec des dépendances circulaires, donc si ces étapes ne vous mènent nulle part, essayez de vérifier la trace de la pile et de vérifier qu'il n'y a pas de dépendances circulaires.

12
hermitt

Le comportement de Lazy<T> est pour mettre en cache les exceptions levées par le ValueFactory . Cela peut conduire à un comportement potentiellement déroutant en raison de la rareté des informations fournies dans le message InvalidOperationException. Microsoft a été informé de ce problème via Connect , cependant, il est marqué comme Ne sera pas corrigé car ils estiment qu'il y a suffisamment d'informations dans l'exception elle-même pour diagnostiquer le problème.

S'il existe une exception interne pour l'IOE que vous recevez, il doit (sans le dire) contenir suffisamment d'informations pour continuer. Une autre possibilité est que vous avez un try...catch blocs qui rejette les exceptions (throw ex; au lieu de throw;), vous perdrez des informations précieuses.

8
user7116

Pour vous assurer que votre exception n'est pas mise en cache, utilisez LazyThreadSafetyMode.PublicationOnly comme deuxième paramètre, au lieu de true.

En utilisant true, vous vous retrouverez avec un LazyThreadSafetyMode.ExecutionAndPublication. Cela garantira qu'un seul thread entre dans la méthode ValueFactory, mais garantit également que les exceptions seront mises en cache.

  private static Lazy<ConfigSource> _cfgSrc = new Lazy<ConfigSource>(
        () => { /* "ValueFactory" here... */ },
        LazyThreadSafetyMode.PublicationOnly);

Voir le lien sixlettervariables fourni pour plus d'informations.

6
nicojs

Lors du chargement paresseux d'une configuration, veillez à ne pas appeler les méthodes qui nécessitent cette configuration. Cela rappellera le chargeur de configuration qui recommence le processus, entraînant l'erreur décrite.

Dans mon cas, je consignais l'état de charge, tandis que l'enregistreur nécessitait une configuration

0
Wouter Vanherck