Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu makale, bu API'nin başvuru belgelerine ek açıklamalar sağlar.
Birden fazla iş parçacığı tarafından okunan ve bir kerede bir iş parçacığı tarafından yazılan bir kaynağı korumak için ReaderWriterLockSlim kullanın. 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.
Uyarı
- 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, ReaderWriterLockSlim'nin performansı ReaderWriterLock'den önemli ölçüde daha iyidir. ReaderWriterLockSlim tüm yeni geliştirmeler için önerilir.
- ReaderWriterLockSlim iş parçacığı durdurma konusunda güvenli değil. 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 ReaderWriterLockSlim örnekleri LockRecursionPolicy.NoRecursion bayrağıyla oluşturulur ve özyinelemeye 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. Mevcut projelerden, Monitor veya ReaderWriterLock kullanan geçişi basitleştirmek için LockRecursionPolicy.SupportsRecursion bayrağını kullanarak özyinelemeye izin veren ReaderWriterLockSlim örnekleri oluşturabilirsiniz.
Bir iş parçacığı kilide üç 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 daha uzun "kilit x moduna girin" ifadesi yerine "enter x mode" tümcesi 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 IDisposable arabirimini uygular. Kullanımını bitirdiğinizde, doğrudan ya da dolaylı yoldan atmalısınız. Türü doğrudan atabilmek için, bir Disposetry/ bloğunda catch yöntemini çağırın. Bunu dolaylı olarak atmak için using (C#'de) veya Using (Visual Basic'te) gibi 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ığı bağlılığı vardır; diğer bir ifadeyle her bir Thread nesne, kilitlilik modlarına geçiş yapmak ve çıkmak için kendi yöntem çağrılarını yapmalıdır. Hiçbir iş parçacığı başka bir iş parçacığının modunu değiştiremez.
Bir ReaderWriterLockSlim özyinelemeye izin vermezse, kilide girmeye çalışan bir iş parçacığı çeşitli nedenlerle engellenebilir.
Okuma moduna girmeye çalışan bir iş parçacığı, yazma moduna girmeyi bekleyen iş parçacıkları varsa veya yazma modunda hâlihazırda tek bir iş parçacığı varsa, bloke olur.
Uyarı
Yazarlar kuyruğa alınırken yeni okuyucuların engellenmesi, yazarlara öncelik veren bir kilit adilliğ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 başka bir iş parçacığı varsa, yazma moduna geçmek için bekleyenler veya yazma modunda olan tek bir iş parçacığı olduğunda bloklanır.
Yazma moduna girmeye çalışan bir iş parçacığı, iş parçacıklarının üç moddan herhangi birinde olması durumunda engellenir.
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 EnterWriteLock veya TryEnterWriteLock yöntemlerini çağırarak 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ükseltme yapan iş parçacığı engellenir. İş 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 çalışan bir iş parçacığı, önce EnterReadLock yöntemini çağırıp sonra ExitUpgradeableReadLock yöntemini çağırarak okuma moduna düşebilir. Bu sürüm düşürme deseni, NoRecursion bile tüm kilit özyineleme politikaları 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
ReaderWriterLockSlim kilit ilkesini belirten oluşturucuyu kullanarak ve ReaderWriterLockSlim(LockRecursionPolicy) belirterek özyinelemeli kilit girişini destekleyen bir LockRecursionPolicy.SupportsRecursion oluşturabilirsiniz.
Uyarı
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. Bu işlemi yapmaya çalışırsa, bir LockRecursionException fırlatı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 moduna girme girişimi engellenir.
Yazma modundaki bir iş parçacığı okuma moduna ve/veya yükseltilebilir moda girebilir ve üç moddan herhangi birini özyinelemeli olarak girebilir.
Kilide 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, o moda girdiği kadar kez çıkmak koşuluyla, girdiği modlardan herhangi bir sırayla çıkabilir. bir iş parçacığı bir moddan çok fazla kez çıkmaya çalışırsa veya girmediği bir moddan çıkmaya çalışırsa, bir SynchronizationLockException oluşturulur.
Kilit durumları
Durumları açısından kilidi 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ığı kendi kilidine girmedi (veya tüm iş parçacıkları kilitten çıktı).
Okuma: Bu durumda, bir veya daha fazla iş parçacığı korunan kaynağa okuma erişimi için kilide girdi.
Uyarı
Bir iş parçacığı, EnterReadLock veya TryEnterReadLock yöntemlerini kullanarak ya da yükseltilebilir moddan düşürerek kilide okuma modunda girebilir.
Yükseltme: Bu durumda, bir iş parçacığı yazma erişimine yükseltme seçeneğiyle (yükseltilebilir modda) okuma erişimi için kilidi aldı ve sıfır veya daha fazla iş parçacığı da okuma erişimi için kilidi aldı. 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 iplik kilide münhasıran sahiptir. Herhangi bir nedenle kilide girmeye çalışan başka bir iş parçacığı 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.
| Geçiş | Girilmeyen (N) | Okuma (R) | Yükseltme (U) | Yazma (W) |
|---|---|---|---|---|
t okuma moduna girer |
t giriyor (R). |
Eğer iş parçacıkları yazma modunu bekliyorsa t bloklanır; aksi takdirde, t girer. |
t yazma modunu bekleyen iş parçacıkları varsa bloke olur; aksi takdirde, t girer.1 |
t Bloklar. |
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 Bloklar. |
t Bloklar. |
t yazma moduna girer |
t (W) girer. |
t Bloklar. |
t Bloklar. 2 |
t Bloklar. |
1 Yükseltilebilir modda başlatılırsa t okuma moduna girer. Bu eylem hiçbir zaman engellenmez. Kilit durumu değişmez. İş parçacığı, yükseltilebilir moddan çıkarak okuma moduna düşürme işlemini daha sonra 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ükseltilir. Kilit durumu Yazma (W) olarak değişir. Eğer t okuma modunda iş parçacıkları olduğu için engelleniyorsa, yazma moduna geçmek isteyen iş parçacıkları olsa bile, son iş parçacığı okuma modundan çıkar çıkmaz yazma moduna girer.
Bir iş parçacığı kilitten çıktığında durum değişikliği meydana geldiğ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ığı devreye girer.
- 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. Bir ReaderWriterLockSlim örneği, iç önbellek işlevi gören Dictionary<TKey,TValue>'e erişimi senkronize etmek 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 rekürsiyona izin vermediğinde, programlamak daha basit ve daha az hataya açık 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, sebze adları sözlüğünü depolamak için SynchronizedCache nesnesini kullanır. Üç 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 {Task.CurrentId} wrote {itemsWritten} items\n");
} ));
// 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 {Task.CurrentId} read {items} items: {output}\n");
} 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($" {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