Cet article a fait l’objet d’une traduction automatique. Pour afficher l’article en anglais, activez la case d’option Anglais. Vous pouvez également afficher le texte anglais dans une fenêtre contextuelle en faisant glisser le pointeur de la souris sur le texte traduit.
Traduction
Anglais

ReaderWriterLockSlim constructeur (LockRecursionPolicy)

 

Date de publication : novembre 2016

Initialise une nouvelle instance de la classe ReaderWriterLockSlim, en spécifiant la stratégie de récurrence du verrou.

Espace de noms:   System.Threading
Assembly:  System.Core (dans System.Core.dll)

public ReaderWriterLockSlim(
	LockRecursionPolicy recursionPolicy
)

Paramètres

recursionPolicy
Type: System.Threading.LockRecursionPolicy

Une des valeurs d'énumération qui spécifie la stratégie de récurrence du verrou.

La stratégie de récurrence détermine les restrictions sur les threads qui entrent plusieurs fois dans le verrou. Par exemple, si un verrou a été créé avec LockRecursionPolicy.NoRecursion et un thread a entré le verrou en mode lecture, LockRecursionException est levée si le thread essaie de réentrer le verrou en mode lecture. De même, si un thread a entré le verrou en mode écriture, LockRecursionException est levée si le thread essaie de réentrer le verrou dans n’importe quel mode.

System_CAPS_noteRemarque

Un thread en mode de mise à niveau peut mettre à niveau en mode écriture ou rétrograder vers le pour mode quel que soit le paramètre de stratégie de récurrence de verrou de lecture.

Quelle que soit la stratégie de récurrence, un thread entré initialement lire en mode n’est pas autorisé à mettre à niveau vers le mode de mise à niveau ou en mode écriture, car ce modèle crée une forte probabilité d’interblocages.

Pour plus d’informations sur la stratégie de récurrence et ses effets, consultez le LockRecursionPolicy énumération et la ReaderWriterLockSlim classe.

L’exemple suivant montre deux scénarios d’exception, qui dépend de le LockRecursionPolicy paramètre et l’autre pas.

Dans le premier scénario, le thread entre en mode lecture et puis essaie d’entrer en mode lecture de façon récursive. Si la ReaderWriterLockSlim est créé à l’aide du constructeur par défaut, qui définit la stratégie de récurrence sur LockRecursionPolicy.NoRecursion, une exception est levée. Si LockRecursionPolicy.SupportsRecursion est utilisé pour créer le ReaderWriterLockSlim, aucune exception n’est levée.

Dans le deuxième scénario, le thread entre en mode lecture, et puis essaie d’entrer en mode écriture. LockRecursionException est levée indépendamment de la stratégie de récurrence du verrou.

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
public class SynchronizedCache 
{
    private ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim();
    private Dictionary<int, string> innerCache = new Dictionary<int, string>();

    public int Count
    { get { return innerCache.Count; } }

    public string Read(int key)
    {
        cacheLock.EnterReadLock();
        try
        {
            return innerCache[key];
        }
        finally
        {
            cacheLock.ExitReadLock();
        }
    }

    public void Add(int key, string value)
    {
        cacheLock.EnterWriteLock();
        try
        {
            innerCache.Add(key, value);
        }
        finally
        {
            cacheLock.ExitWriteLock();
        }
    }

    public bool AddWithTimeout(int key, string value, int timeout)
    {
        if (cacheLock.TryEnterWriteLock(timeout))
        {
            try
            {
                innerCache.Add(key, value);
            }
            finally
            {
                cacheLock.ExitWriteLock();
            }
            return true;
        }
        else
        {
            return false;
        }
    }

    public AddOrUpdateStatus AddOrUpdate(int key, string value)
    {
        cacheLock.EnterUpgradeableReadLock();
        try
        {
            string result = null;
            if (innerCache.TryGetValue(key, out result))
            {
                if (result == value)
                {
                    return AddOrUpdateStatus.Unchanged;
                }
                else
                {
                    cacheLock.EnterWriteLock();
                    try
                    {
                        innerCache[key] = value;
                    }
                    finally
                    {
                        cacheLock.ExitWriteLock();
                    }
                    return AddOrUpdateStatus.Updated;
                }
            }
            else
            {
                cacheLock.EnterWriteLock();
                try
                {
                    innerCache.Add(key, value);
                }
                finally
                {
                    cacheLock.ExitWriteLock();
                }
                return AddOrUpdateStatus.Added;
            }
        }
        finally
        {
            cacheLock.ExitUpgradeableReadLock();
        }
    }

    public void Delete(int key)
    {
        cacheLock.EnterWriteLock();
        try
        {
            innerCache.Remove(key);
        }
        finally
        {
            cacheLock.ExitWriteLock();
        }
    }

    public enum AddOrUpdateStatus
    {
        Added,
        Updated,
        Unchanged
    };

    ~SynchronizedCache()
    {
       if (cacheLock != null) cacheLock.Dispose();
    }
}

Le code suivant utilise ensuite le SynchronizedCache objet à stocker un dictionnaire de noms légumes. Il crée trois tâches. La première écrit les noms des légumes stockés dans un tableau à un SynchronizedCache instance. La deuxième et troisième tâche Afficher les noms des légumes, le premier dans l’ordre croissant (de l’index faible à l’index élevé), le second dans l’ordre décroissant. La dernière tâche recherche la chaîne « cucumber » et, lorsqu’il la trouve, appelle le EnterUpgradeableReadLock méthode pour remplacer la chaîne « bean vert ».

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
public class Example
{
   public static void Main()
   {
      var sc = new SynchronizedCache();
      var tasks = new List<Task>();
      int itemsWritten = 0;

      // Execute a writer.
      tasks.Add(Task.Run( () => { String[] vegetables = { "broccoli", "cauliflower",
                                                          "carrot", "sorrel", "baby turnip",
                                                          "beet", "brussel sprout",
                                                          "cabbage", "plantain",
                                                          "spinach", "grape leaves",
                                                          "lime leaves", "corn",
                                                          "radish", "cucumber",
                                                          "raddichio", "lima beans" };
                                  for (int ctr = 1; ctr <= vegetables.Length; ctr++)
                                     sc.Add(ctr, vegetables[ctr - 1]);

                                  itemsWritten = vegetables.Length;
                                  Console.WriteLine("Task {0} wrote {1} items\n",
                                                    Task.CurrentId, itemsWritten);
                                } ));
      // Execute two readers, one to read from first to last and the second from last to first.
      for (int ctr = 0; ctr <= 1; ctr++) {
         bool desc = Convert.ToBoolean(ctr);
         tasks.Add(Task.Run( () => { int start, last, step;
                                     int items;
                                     do {
                                        String output = String.Empty;
                                        items = sc.Count;
                                        if (! desc) {
                                           start = 1;
                                           step = 1;
                                           last = items;
                                        }
                                        else {
                                           start = items;
                                           step = -1;
                                           last = 1;
                                        }

                                        for (int index = start; desc ? index >= last : index <= last; index += step)
                                           output += String.Format("[{0}] ", sc.Read(index));

                                        Console.WriteLine("Task {0} read {1} items: {2}\n",
                                                          Task.CurrentId, items, output);
                                     } while (items < itemsWritten | itemsWritten == 0);
                             } ));
      }
      // Execute a red/update task.
      tasks.Add(Task.Run( () => { Thread.Sleep(100);
                                  for (int ctr = 1; ctr <= sc.Count; ctr++) {
                                     String value = sc.Read(ctr);
                                     if (value == "cucumber")
                                        if (sc.AddOrUpdate(ctr, "green bean") != SynchronizedCache.AddOrUpdateStatus.Unchanged)
                                           Console.WriteLine("Changed 'cucumber' to 'green bean'");
                                  }
                                } ));

      // Wait for all three tasks to complete.
      Task.WaitAll(tasks.ToArray());

      // Display the final contents of the cache.
      Console.WriteLine();
      Console.WriteLine("Values in synchronized cache: ");
      for (int ctr = 1; ctr <= sc.Count; ctr++)
         Console.WriteLine("   {0}: {1}", ctr, sc.Read(ctr));

   }
}
// The example displays the following output:
//    Task 1 read 0 items:
//
//    Task 3 wrote 17 items
//
//
//    Task 1 read 17 items: [broccoli] [cauliflower] [carrot] [sorrel] [baby turnip] [
//    beet] [brussel sprout] [cabbage] [plantain] [spinach] [grape leaves] [lime leave
//    s] [corn] [radish] [cucumber] [raddichio] [lima beans]
//
//    Task 2 read 0 items:
//
//    Task 2 read 17 items: [lima beans] [raddichio] [cucumber] [radish] [corn] [lime
//    leaves] [grape leaves] [spinach] [plantain] [cabbage] [brussel sprout] [beet] [b
//    aby turnip] [sorrel] [carrot] [cauliflower] [broccoli]
//
//    Changed 'cucumber' to 'green bean'
//
//    Values in synchronized cache:
//       1: broccoli
//       2: cauliflower
//       3: carrot
//       4: sorrel
//       5: baby turnip
//       6: beet
//       7: brussel sprout
//       8: cabbage
//       9: plantain
//       10: spinach
//       11: grape leaves
//       12: lime leaves
//       13: corn
//       14: radish
//       15: green bean
//       16: raddichio
//       17: lima beans

Plateforme Windows universelle
Disponible depuis 8
.NET Framework
Disponible depuis 3.5
Bibliothèque de classes portable
Pris en charge dans : plateformes .NET portables
Silverlight pour Windows Phone
Disponible depuis 8.0
Windows Phone
Disponible depuis 8.1
Retour au début
Afficher: