31 votes

Le rendement C # libère-t-il un verrou?

J'ai la méthode suivante:

 public static IEnumerable<Dictionary<string, object>> GetRowsIter
   (this SqlCeResultSet resultSet)
{
    // Make sure we don't multi thread the database.
    lock (Database)
    {
        if (resultSet.HasRows)
        {
            resultSet.Read();

            do
            {
                var resultList = new Dictionary<string, object>();
                for (int i = 0; i < resultSet.FieldCount; i++)
                {
                    var value = resultSet.GetValue(i);
                    resultList.Add(resultSet.GetName(i), value == DBNull.Value 
                                                                  ? null : value);
                }
                yield return resultList;
            } while (resultSet.Read());
        }
        yield break;
    }
 

Je viens d'ajouter le lock(Database) pour essayer de résoudre certains problèmes de concordance. Je suis curieux cependant, le yield return libérera-t-il le verrou sur Database , puis le reverrouillera quand il ira pour la prochaine itération? Ou Database resteront-ils verrouillés pendant toute la durée de l'itération?

20voto

JaredPar Points 333733

Pas de l' yield return ne causera pas de verrous pour être libéré / déverrouillé. L' lock déclaration de développer sur un try / finally bloc et l'itérateur ne sera pas traiter ce différemment explicite try / finally dans la méthode de l'itérateur.

Les détails sont un peu plus compliquées, mais les règles de base pour quand un finally bloc sera exécuté à l'intérieur d'une méthode d'itérateur est

  1. Lorsque l'itérateur est suspendue et l' Dispose est appelé l' finally blocs portée au point de la suspension sera exécuté
  2. Lorsque l'itérateur est en cours d'exécution et le code entraînerait par ailleurs une finally le finally bloc s'exécute.
  3. Lorsque l'itérateur rencontre un yield break déclaration de l' finally blocs portée au point de la yield break sera exécuté

13voto

Marc Gravell Points 482669

La serrure se traduit par try/finally (normal c#)

Dans Itérateur blocs (aka rendement), "enfin", devient une partie de la IDisposable.Dispose() de la mise en œuvre de l' agent recenseur. Ce code est également invoquée à l'interne lorsque vous consommez de la dernière de ces données.

"foreach" appelle automatiquement Dispose(), donc si vous de consommer à "foreach" (ou regualar LINQ etc...) il va être débloqué.

Toutefois, si l'appelant utilise GetEnumerator() directement (très rare) et de ne pas lire toutes les données et ne pas appeler dispose() alors que le verrou ne sera pas publié.

Je dois vérifier pour voir si ou obtient un finaliser; il pourrait obtenir libéré par GC, mais je ne voudrais pas parier de l'argent sur elle.

5voto

driis Points 70872

L'objet Database sera verrouillé jusqu'à la fin de l'itération (ou l'itérateur est supprimé).

Cela pourrait entraîner des périodes de verrouillage excessives, et je déconseille de le faire comme ça.

2voto

Otávio Décio Points 44200

Le verrouillage reste en vigueur jusqu'à ce que vous sortiez de la portée de lock (). Céder ne fait pas cela.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X