System.Threading.ReaderWriterLockSlim sınıfı
Bu makale, bu API'nin başvuru belgelerine ek açıklamalar sağlar.
Birden çok iş parçacığı tarafından okunan ve bir kerede bir iş parçacığı tarafından yazılan bir kaynağı korumak için kullanın ReaderWriterLockSlim . ReaderWriterLockSlim birden çok iş parçacığının okuma modunda olmasına izin verir, bir iş parçacığının kilidin özel sahipliğiyle yazma modunda olmasını sağlar ve okuma erişimi olan bir iş parçacığının kaynağa okuma erişiminden feragat etmek zorunda kalmadan yazma moduna yükseltebildiği yükseltilebilir okuma modunda olmasına olanak tanır.
Not
- ReaderWriterLockSlim ile benzerdir ReaderWriterLock, ancak özyineleme ve kilit durumunu yükseltme ve düşürme için basitleştirilmiş kuralları vardır. ReaderWriterLockSlim olası kilitlenme durumlarının çoğunu önler. Buna ek olarak, 'nin performansı değerinden ReaderWriterLockSlim önemli ölçüde daha ReaderWriterLockiyidir. ReaderWriterLockSlim tüm yeni geliştirmeler için önerilir.
- ReaderWriterLockSlim iş parçacığı durdurma güvenli değildir. Buna erişen iş parçacıklarının .NET Framework gibi durdurulabileceği bir ortamda kullanmamalısınız. .NET Core veya .NET 5+ kullanıyorsanız sorun olmaz. Abort .NET Core'da desteklenmez ve .NET 5 ve sonraki sürümlerde eskidir .
Varsayılan olarak, yeni örnekleri ReaderWriterLockSlim bayrağıyla LockRecursionPolicy.NoRecursion oluşturulur ve özyinelemelere izin vermez. Özyineleme gereksiz komplikasyonlara neden olduğundan ve kodunuzu kilitlenmelere daha açık hale getirdiği için bu varsayılan ilke tüm yeni geliştirmeler için önerilir. veya ReaderWriterLockkullanan Monitor mevcut projelerden geçişi basitleştirmek için bayrağını LockRecursionPolicy.SupportsRecursion kullanarak özyinelemeye izin veren örnekleri ReaderWriterLockSlim oluşturabilirsiniz.
İş parçacığı kilidi üç modda girebilir: okuma modu, yazma modu ve yükseltilebilir okuma modu. (Bu konunun geri kalanında ,"yükseltilebilir okuma modu" "yükseltilebilir mod" olarak adlandırılır ve "enter x
mode" tümceciği daha uzun "kilit x
moduna girin" ifadesi tercih edilir.)
Özyineleme ilkesinden bağımsız olarak, her zaman yalnızca bir iş parçacığı yazma modunda olabilir. bir iş parçacığı yazma modundayken, başka hiçbir iş parçacığı herhangi bir modda kilidi giremez. Herhangi bir anda yalnızca bir iş parçacığı yükseltilebilir modda olabilir. Herhangi bir sayıda iş parçacığı okuma modunda olabilir ve diğer iş parçacıkları okuma modundayken yükseltilebilir modda bir iş parçacığı olabilir.
Önemli
Bu tür arabirimini IDisposable uygular. Türünü kullanmayı bitirdiğinizde, doğrudan veya dolaylı olarak atmalısınız. Türü doğrudan atmak için yöntemini bir try
/catch
blok içinde çağırın.Dispose Bunu dolaylı olarak atmak için (C#'de) veya Using
(Visual Basic'te) gibi using
bir dil yapısı kullanın. Daha fazla bilgi için arabirim konusunun "IDisposable Uygulayan Bir Nesne Kullanma" bölümüne IDisposable bakın.
ReaderWriterLockSlim yönetilen iş parçacığı benzitesi vardır; diğer bir ifadeyle, her Thread nesnenin kilit modlarına girmek ve modlarından çıkmak için kendi yöntem çağrılarını yapması gerekir. Hiçbir iş parçacığı başka bir iş parçacığının modunu değiştiremez.
bir ReaderWriterLockSlim özyinelemeye izin vermezse, kilidi girmeye çalışan bir iş parçacığı çeşitli nedenlerle engelleyebilir:
Yazma moduna girmeyi bekleyen iş parçacıkları varsa veya yazma modunda tek bir iş parçacığı varsa, okuma moduna girmeye çalışan iş parçacığı blokları.
Not
Yazarlar kuyruğa alınırken yeni okuyucuların engellenmesi, yazarları destekleyen bir kilit eşitliği ilkesidir. Geçerli eşitlik ilkesi, en yaygın senaryolarda aktarım hızını artırmak için okuyuculara ve yazarlara eşitliği dengeler. .NET'in gelecekteki sürümleri yeni eşitlik ilkelerine neden olabilir.
Yükseltilebilir moda girmeye çalışan bir iş parçacığı, zaten yükseltilebilir modda bir iş parçacığı varsa, yazma moduna girmeyi bekleyen iş parçacıkları varsa veya yazma modunda tek bir iş parçacığı varsa bloklar.
Yazma moduna girmeye çalışan bir iş parçacığı, üç moddan birinde bir iş parçacığı varsa bloklar.
Kilitleri yükseltme ve düşürme
Yükseltilebilir mod, bir iş parçacığının genellikle korumalı kaynaktan okuduğu, ancak bir koşul karşılandığında buna yazması gerekebileceği durumlar için tasarlanmıştır. Yükseltilebilir moda giren bir ReaderWriterLockSlim iş parçacığı korumalı kaynağa okuma erişimine sahiptir ve veya TryEnterWriteLock yöntemlerini çağırarak EnterWriteLock yazma moduna yükseltebilir. Aynı anda yükseltilebilir modda yalnızca bir iş parçacığı olabileceğinden, özyineleme izin verilmediğinde yazma moduna yükseltme işlemi kilitlenemez. Bu varsayılan ilkedir.
Önemli
Özyineleme ilkesinden bağımsız olarak, başlangıçta okuma moduna giren bir iş parçacığının yükseltilebilir moda veya yazma moduna yükseltilmesine izin verilmez, çünkü bu düzen kilitlenme olasılığı güçlü bir şekilde oluşturur. Örneğin, okuma modundaki iki iş parçacığı da yazma moduna girmeye çalışırsa çıkmaza girer. Yükseltilebilir mod, bu tür kilitlenmeleri önlemek için tasarlanmıştır.
Okuma modunda başka iş parçacıkları varsa, yükselten iş parçacığı engeller. İş parçacığı engellenmiş olsa da, okuma moduna girmeye çalışan diğer iş parçacıkları engellenir. Tüm iş parçacıkları okuma modundan çıktığında engellenen yükseltilebilir iş parçacığı yazma moduna girer. Yazma moduna girmeyi bekleyen başka iş parçacıkları varsa, yükseltilebilir modda olan tek iş parçacığının kaynağa özel erişim kazanmasını engellediği için bunlar engellenmiş durumda kalır.
Yükseltilebilir modda iş parçacığı yazma modundan çıktığında, yazma moduna girmeyi bekleyen iş parçacıkları olmadığı sürece, okuma moduna girmeyi bekleyen diğer iş parçacıkları bunu yapabilir. Yükseltilebilir modda iş parçacığı, korumalı kaynağa yazan tek iş parçacığı olduğu sürece süresiz olarak yükseltilebilir ve düşürülebilir.
Önemli
Birden çok iş parçacığının yazma moduna veya yükseltilebilir moda girmesine izin verirseniz, bir iş parçacığının yükseltilebilir modu tekeline almasına izin vermemelisiniz. Aksi takdirde, doğrudan yazma moduna girmeye çalışan iş parçacıkları süresiz olarak engellenir ve engellenirken diğer iş parçacıkları okuma moduna giremez.
Yükseltilebilir modda bir iş parçacığı, önce yöntemini çağırıp ardından yöntemini çağırarak EnterReadLockExitUpgradeableReadLock okuma moduna düşürebilir. Bu sürüm düşürme düzeni, bile tüm NoRecursionkilit özyineleme ilkeleri için izin verilir.
Okuma moduna düşürme işleminden sonra, iş parçacığı okuma modundan çıkana kadar yükseltilebilir moda yeniden giremez.
Kilidi özyinelemeli olarak girin
Kilit ilkesini belirten oluşturucuyu ReaderWriterLockSlim(LockRecursionPolicy) kullanarak ve belirterek LockRecursionPolicy.SupportsRecursionözyinelemeli kilit girişini destekleyen bir ReaderWriterLockSlim oluşturabilirsiniz.
Not
Yeni geliştirme için özyineleme kullanılması önerilmez, çünkü gereksiz komplikasyonlara neden olur ve kodunuzu kilitlenmelere daha açık hale getirir.
Özyineleme sağlayan bir ReaderWriterLockSlim için, bir iş parçacığının girebileceği modlar hakkında aşağıdakiler söylenebilir:
Okuma modundaki bir iş parçacığı yinelemeli olarak okuma moduna girebilir, ancak yazma moduna veya yükseltilebilir moda giremez. Bunu yapmaya çalışırsa, bir LockRecursionException atılır. Okuma moduna girmek ve sonra yazma moduna veya yükseltilebilir moda girmek, kilitlenme olasılığı yüksek olan bir desendir, bu nedenle buna izin verilmez. Daha önce açıklandığı gibi, bir kilidi yükseltmenin gerekli olduğu durumlar için yükseltilebilir mod sağlanır.
Yükseltilebilir modda bir iş parçacığı yazma moduna ve/veya okuma moduna girebilir ve üç moddan herhangi birini özyinelemeli olarak girebilir. Ancak, okuma modunda başka iş parçacıkları varsa yazma modu blokları girme girişimi.
Yazma modundaki bir iş parçacığı okuma moduna ve/veya yükseltilebilir moda girebilir ve üç moddan herhangi birini özyinelemeli olarak girebilir.
Kilidi girmemiş bir iş parçacığı herhangi bir moda girebilir. Bu girişim, özyinelemeli olmayan bir kilit girme girişimiyle aynı nedenlerle engelleyebilir.
Bir iş parçacığı, her moddan tam olarak o moda girdiği kadar çok kez çıktığı sürece, girdiği modlardan herhangi bir sırayla çıkabilirsiniz. bir iş parçacığı bir moddan çok fazla kez çıkmaya çalışırsa veya girmediği bir moddan çıkmaya çalışırsa, bir SynchronizationLockException oluşturulur.
Durumları kilitleme
Kilidi durumları açısından düşünmek yararlı olabilir. A ReaderWriterLockSlim dört durumdan birinde olabilir: girilmedi, okundu, yükseltildi ve yazılamadı.
Girilmedi: Bu durumda, hiçbir iş parçacığı kilitlenmedi (veya tüm iş parçacıkları kilitte çıktı).
Okuma: Bu durumda, korumalı kaynağa okuma erişimi için bir veya daha fazla iş parçacığı kilit girdi.
Not
İş parçacığı, veya yöntemlerini kullanarak EnterReadLock veya TryEnterReadLock yükseltilebilir moddan düşürerek kilidi okuma moduna girebilir.
Yükseltme: Bu durumda, bir iş parçacığı yazma erişimine yükseltme seçeneğiyle (yükseltilebilir modda) okuma erişimi kilidine girdi ve sıfır veya daha fazla iş parçacığı okuma erişimi için kilit girdi. Aynı anda birden fazla iş parçacığı, yükseltme seçeneğiyle kilidi giremez; yükseltilebilir moda girmeye çalışan ek iş parçacıkları engellenir.
Yazma: Bu durumda, korumalı kaynağa yazma erişimi için bir iş parçacığı kilit girdi. O ipliğin kilidi özel olarak ele geçirildi. Herhangi bir nedenle kilidi girmeye çalışan diğer tüm iş parçacıkları engellenir.
Aşağıdaki tabloda, bir iş parçacığı t
en soldaki sütunda açıklanan eylemi gerçekleştirdiğinde özyineleme izin verilmeyen kilitler için kilit durumları arasındaki geçişler açıklanmaktadır. Eylemi gerçekleştirmesi sırasında t
modu yoktur. (Yükseltilebilir modda olduğu t
özel durum tablo dipnotlarında açıklanmıştır.) Üst satır, kilidin başlangıç durumunu açıklar. Hücreler iş parçacığına ne olduğunu açıklar ve kilit durumundaki değişiklikleri parantez içinde gösterir.
Transition | Girilmedi (N) | Okuma (R) | Yükseltme (U) | Yazma (W) |
---|---|---|---|---|
t okuma moduna girer |
t enters (R). |
t iş parçacıkları yazma modunu bekliyorsa bloklar; aksi takdirde, t girer. |
t iş parçacıkları yazma modunu bekliyorsa bloklar; aksi takdirde, t girer.1 |
t Blok. |
t yükseltilebilir moda girer |
t enters (U). |
t iş parçacıkları yazma modunu veya yükseltme modunu bekliyorsa bloklar; aksi takdirde ( t U) değerini girer. |
t Blok. |
t Blok. |
t yazma moduna girer |
t enters (W). |
t Blok. |
t Blok.2 |
t Blok. |
1 Yükseltilebilir modda başlatılırsa t
okuma moduna girer. Bu eylem hiçbir zaman engellemez. Kilit durumu değişmez. (İş parçacığı daha sonra yükseltilebilir moddan çıkararak okuma moduna düşürme işlemini tamamlayabilir.)
2 Yükseltilebilir modda başlatılırsa t
, okuma modunda iş parçacıkları olup olmadığını engeller. Aksi takdirde yazma moduna yükseltildi. Kilit durumu Yazma (W) olarak değişir. Okuma modunda iş parçacıkları olduğundan engellerse t
, yazma moduna girmeyi bekleyen iş parçacıkları olsa bile son iş parçacığı okuma modundan çıkar çıkmaz yazma moduna girer.
bir iş parçacığı kilit çıkışından çıktığı için durum değişikliği gerçekleştiğinde, uyandırılacak sonraki iş parçacığı aşağıdaki gibi seçilir:
- İlk olarak, yazma modunu bekleyen ve zaten yükseltilebilir modda olan bir iş parçacığı (en fazla böyle bir iş parçacığı olabilir).
- Bu başarısız olursa, yazma modunu bekleyen bir iş parçacığı.
- Bu başarısız olursa, yükseltilebilir modu bekleyen bir iş parçacığı.
- Bu başarısız olursa, okuma modunu bekleyen tüm iş parçacıkları.
Kilidin sonraki durumu her zaman ilk iki durumda Yazma (W) ve üçüncü durumda, çıkış iş parçacığı durum değişikliğini tetiklediğinde kilidin durumundan bağımsız olarak Yükseltme (U) şeklindedir. Son durumda, durum değişikliğinden sonra yükseltilebilir modda bir iş parçacığı varsa kilidin durumu Yükselt (U) ve önceki durumdan bağımsız olarak Okuma (R) şeklindedir.
Örnekler
Aşağıdaki örnekte, tamsayı anahtarlı dizeleri tutan basit bir eşitlenmiş önbellek gösterilmektedir. örneği ReaderWriterLockSlim , iç önbellek görevi görecek öğesine Dictionary<TKey,TValue> erişimi eşitlemek için kullanılır.
Örnek önbelleğe eklemek, önbellekten silmek ve önbellekten okumak için basit yöntemler içerir. Zaman aşımlarını göstermek için örnek, yalnızca belirli bir zaman aşımı içinde bunu gerçekleştirebiliyorsa önbelleğe ekleyen bir yöntem içerir.
Yükseltilebilir modu göstermek için örnek, bir anahtarla ilişkili değeri alan ve yeni bir değerle karşılaştıran bir yöntem içerir. Değer değişmezse, yöntem değişiklik olmadığını belirten bir durum döndürür. Anahtar için değer bulunamazsa anahtar/değer çifti eklenir. Değer değiştiyse güncelleştirilir. Yükseltilebilir mod, iş parçacığının kilitlenme riski olmadan okuma erişiminden gerektiğinde yazma erişimine yükseltmesine olanak tanır.
Örnek, yükseltilebilir modu gösteren yöntemin dönüş değerlerini belirten iç içe sabit listesi içerir.
Örnek, kilidi oluşturmak için parametresiz oluşturucuyu kullandığından özyineleme işlemine izin verilmez. ReaderWriterLockSlim kilit özyineleme izin vermediğinde programlama daha basit ve hataya daha az eğilimli olur.
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
Imports System.Collections.Generic
Imports System.Threading
Imports System.Threading.Tasks
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();
}
}
Public Class SynchronizedCache
Private cacheLock As New ReaderWriterLockSlim()
Private innerCache As New Dictionary(Of Integer, String)
Public ReadOnly Property Count As Integer
Get
Return innerCache.Count
End Get
End Property
Public Function Read(ByVal key As Integer) As String
cacheLock.EnterReadLock()
Try
Return innerCache(key)
Finally
cacheLock.ExitReadLock()
End Try
End Function
Public Sub Add(ByVal key As Integer, ByVal value As String)
cacheLock.EnterWriteLock()
Try
innerCache.Add(key, value)
Finally
cacheLock.ExitWriteLock()
End Try
End Sub
Public Function AddWithTimeout(ByVal key As Integer, ByVal value As String, _
ByVal timeout As Integer) As Boolean
If cacheLock.TryEnterWriteLock(timeout) Then
Try
innerCache.Add(key, value)
Finally
cacheLock.ExitWriteLock()
End Try
Return True
Else
Return False
End If
End Function
Public Function AddOrUpdate(ByVal key As Integer, _
ByVal value As String) As AddOrUpdateStatus
cacheLock.EnterUpgradeableReadLock()
Try
Dim result As String = Nothing
If innerCache.TryGetValue(key, result) Then
If result = value Then
Return AddOrUpdateStatus.Unchanged
Else
cacheLock.EnterWriteLock()
Try
innerCache.Item(key) = value
Finally
cacheLock.ExitWriteLock()
End Try
Return AddOrUpdateStatus.Updated
End If
Else
cacheLock.EnterWriteLock()
Try
innerCache.Add(key, value)
Finally
cacheLock.ExitWriteLock()
End Try
Return AddOrUpdateStatus.Added
End If
Finally
cacheLock.ExitUpgradeableReadLock()
End Try
End Function
Public Sub Delete(ByVal key As Integer)
cacheLock.EnterWriteLock()
Try
innerCache.Remove(key)
Finally
cacheLock.ExitWriteLock()
End Try
End Sub
Public Enum AddOrUpdateStatus
Added
Updated
Unchanged
End Enum
Protected Overrides Sub Finalize()
If cacheLock IsNot Nothing Then cacheLock.Dispose()
End Sub
End Class
Aşağıdaki kod daha sonra nesnesini kullanarak sebze adları sözlüğü depolar SynchronizedCache
. Üç görev oluşturur. birincisi bir dizide depolanan sebzelerin adlarını bir SynchronizedCache
örneğe yazar. İkinci ve üçüncü görev, birinci artan sırada (düşük dizinden yüksek dizine), ikincisi azalan sırada olan sebzelerin adlarını görüntüler. Son görev "salatalık" dizesini arar ve bulduğunda "yeşil fasulye" dizesini değiştirmek için yöntemini çağırır EnterUpgradeableReadLock .
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
Imports System.Collections.Generic
Imports System.Threading
Imports System.Threading.Tasks
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 = ctr == 1;
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
Public Module Example
Public Sub Main()
Dim sc As New SynchronizedCache()
Dim tasks As New List(Of Task)
Dim itemsWritten As Integer
' Execute a writer.
tasks.Add(Task.Run( Sub()
Dim vegetables() As String = { "broccoli", "cauliflower",
"carrot", "sorrel", "baby turnip",
"beet", "brussel sprout",
"cabbage", "plantain",
"spinach", "grape leaves",
"lime leaves", "corn",
"radish", "cucumber",
"raddichio", "lima beans" }
For ctr As Integer = 1 to vegetables.Length
sc.Add(ctr, vegetables(ctr - 1))
Next
itemsWritten = vegetables.Length
Console.WriteLine("Task {0} wrote {1} items{2}",
Task.CurrentId, itemsWritten, vbCrLf)
End Sub))
' Execute two readers, one to read from first to last and the second from last to first.
For ctr As Integer = 0 To 1
Dim flag As Integer = ctr
tasks.Add(Task.Run( Sub()
Dim start, last, stp As Integer
Dim items As Integer
Do
Dim output As String = String.Empty
items = sc.Count
If flag = 0 Then
start = 1 : stp = 1 : last = items
Else
start = items : stp = -1 : last = 1
End If
For index As Integer = start To last Step stp
output += String.Format("[{0}] ", sc.Read(index))
Next
Console.WriteLine("Task {0} read {1} items: {2}{3}",
Task.CurrentId, items, output,
vbCrLf)
Loop While items < itemsWritten Or itemsWritten = 0
End Sub))
Next
' Execute a red/update task.
tasks.Add(Task.Run( Sub()
For ctr As Integer = 1 To sc.Count
Dim value As String = sc.Read(ctr)
If value = "cucumber" Then
If sc.AddOrUpdate(ctr, "green bean") <> SynchronizedCache.AddOrUpdateStatus.Unchanged Then
Console.WriteLine("Changed 'cucumber' to 'green bean'")
End If
End If
Next
End Sub ))
' 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 ctr As Integer = 1 To sc.Count
Console.WriteLine(" {0}: {1}", ctr, sc.Read(ctr))
Next
End Sub
End Module
' The example displays output like the following:
' 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