Was this page helpful?
Your feedback about this content is important. Let us know what you think.
Additional feedback?
1500 characters remaining
Export (0) Print
Expand All

ReaderWriterLockSlim Constructor (LockRecursionPolicy)

Initializes a new instance of the ReaderWriterLockSlim class, specifying the lock recursion policy.

Namespace:  System.Threading
Assemblies:   System.Threading (in System.Threading.dll)
  System.Core (in System.Core.dll)

public ReaderWriterLockSlim(
	LockRecursionPolicy recursionPolicy
)

Parameters

recursionPolicy
Type: System.Threading.LockRecursionPolicy

One of the enumeration values that specifies the lock recursion policy.

Recursion policy determines the restrictions on threads that enter the lock more than once. For example, if a lock was created with LockRecursionPolicy.NoRecursion and a thread has entered the lock in read mode, LockRecursionException is thrown if the thread tries to reenter the lock in read mode. Similarly, if a thread has entered the lock in write mode, LockRecursionException is thrown if the thread tries to reenter the lock in any mode.

NoteNote

A thread in upgradeable mode can upgrade to write mode or downgrade to read mode regardless of the lock recursion policy setting.

Regardless of recursion policy, a thread that initially entered read mode is not allowed to upgrade to upgradeable mode or write mode, because that pattern creates a strong probability of deadlocks.

For more information about recursion policy and its effects, see the LockRecursionPolicy enumeration and the ReaderWriterLockSlim class.

The following example shows two exception scenarios, one that depends on the LockRecursionPolicy setting and one that does not.

In the first scenario, the thread enters read mode and then tries to enter read mode recursively. If the ReaderWriterLockSlim is created by using the default constructor, which sets recursion policy to LockRecursionPolicy.NoRecursion, an exception is thrown. If LockRecursionPolicy.SupportsRecursion is used to create the ReaderWriterLockSlim, no exception is thrown.

In the second scenario, the thread enters read mode and then tries to enter write mode. LockRecursionException is thrown regardless of the lock recursion policy.

The following code then uses the SynchronizedCache object to store a dictionary of vegetable names. It creates three tasks. The first writes the names of vegetables stored in an array to a SynchronizedCache instance. The second and third task display the names of the vegetables, the first in ascending order (from low index to high index), the second in descending order. The final task searches for the string "cucumber" and, when it finds it, calls the EnterUpgradeableReadLock method to substitute the string "green bean".

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

.NET Framework

Supported in: 4.6, 4.5, 4, 3.5

.NET Framework Client Profile

Supported in: 4, 3.5 SP1

.NET for Windows Phone apps

Supported in: Windows Phone 8.1, Windows Phone Silverlight 8.1, Windows Phone Silverlight 8

Portable Class Library

Supported in: Portable Class Library
Show:
© 2015 Microsoft