Souběžné kolekce v .Net jsou obsaženy uvnitř oboru názvů System.Collections.Concurrent a poskytují bezzámkové a bezpečné implementace tříd tříd. Kolekce bezpečné pro vlákna byly poprvé představeny v .Net 4 a kolekce byly poprvé představeny jako součást .Net Framework 1.0 a byly k dispozici v oboru názvů System.Collections.
Můžete využít výhod souběžných kolekcí pro práci s kolekcemi bez nutnosti psát jakýkoli další kód pro synchronizaci vláken. Můžete se podívat na můj článek o ConcurrentStack a ConcurrentQueue.
ConcurrentBag
ConcurrentBag poskytuje vláknově bezpečnou kolekci neuspořádané sady prvků. Zde je seznam důležitých metod třídy ConcurrentBag.
- Přidat (T prvek) - Tato metoda se používá k přidání prvku do ConcurrentBag.
- TryPeek (out T) - Tato metoda se používá k načtení prvku z ConcurrentBag bez jeho odebrání.
- TryTake (out T) - Tato metoda se používá k načtení prvku z ConcurrentBag. Tato metoda odstraní položku z kolekce.
Následující fragment kódu ukazuje, jak můžete vytvořit kolekci ConcurrentBag a ukládat do ní položky.
ConcurrentBag concurrentBag = nový ConcurrentBag ();
pro (int i = 0; i <10; i ++)
{
concurrentBag.Add (i);
}
Pokud byste měli načíst položky v kolekci, měli byste napsat následující kód:
while (concurrentBag.Count> 0)
{
Prvek Int32;
if (concurrentBag.TryTake (out element))
{
Console.WriteLine (prvek);
}
}
Všimněte si, jak byla použita metoda TryTake: Vrací true při úspěchu, jinak false. Metoda TryTake také odebere položku z kolekce. Smyčka while pokračuje v provádění, dokud není počet položek v kolekci větší než nula. Zde je kompletní seznam kódů pro vaši referenci.
static void Main (řetězec [] args)
{
ConcurrentBag concurrentBag = nový ConcurrentBag ();
pro (int i = 0; i <10; i ++)
{
concurrentBag.Add (i);
}
while (concurrentBag.Count> 0)
{
Prvek Int32;
if (concurrentBag.TryTake (out element))
{
Console.WriteLine (prvek);
}
}
Console.Read ();
}
Souběžný slovník
Slovník je obecná sbírka párů klíč / hodnota. Je to rychlejší než hashtable, protože eliminuje režii boxu a un-boxu. ConcurrentDictionary je obsažen uvnitř System.Collections.Concurrent oboru názvů a představuje slovník bezpečný pro vlákna.
Mezi důležité členy třídy ConcurrentDictionary patří následující:
- TryAdd: Tato metoda se používá k přidání položky v instanci ConcurrentDictionary. Všimněte si, že tato metoda vyvolá výjimku, pokud je klíč již v kolekci přítomen.
- TryGetValue: Tato metoda se používá k načtení položky z kolekce.
- TryRemove: Tato metoda se používá k odebrání položky z kolekce.
- TryUpdate: Tato metoda se používá k aktualizaci konkrétního klíče v instanci ConcurrentDictionary pomocí nové zadané hodnoty.
Následující fragment kódu ukazuje, jak můžete vytvořit instanci ConcurrentDictionary a přidat do ní položky:
ConcurrentDictionary obj = new ConcurrentDictionary ();
obj.TryAdd ("X001", "Toto je první hodnota.");
obj.TryAdd ("X002", "Toto je druhá hodnota.");
Pokud se nyní pokusíte přidat další položku, ale se stejným klíčem, nezdaří se to. Viz níže uvedený fragment kódu.
bool success = obj.TryAdd ("X002", "Toto je třetí hodnota.");
Hodnota proměnné success je „false“, protože pokus o přidání hodnoty se stejným klíčem selže.
Následující fragment kódu ukazuje, jak můžete načíst položku z kolekce na základě klíče.
string item = null;
bool isExist = obj.TryGetValue ("X001", mimo položku);
Pokud byste chtěli načíst všechny položky v kolekci, můžete místo toho použít následující fragment kódu.
foreach (var v in obj)
{
Console.WriteLine (v.Key + "---" + v.Value);
}
Následující fragment kódu ukazuje, jak můžete odebrat položku z kolekce.
string item = null;
bool result = obj.TryRemove ("X001", mimo položku);
Pokud byste chtěli odebrat všechny položky, lze místo toho použít následující fragment kódu.
obj.Clear ();
Zvažte následující dvě statické metody.
static void FirstTask (ConcurrentDictionary obj)
{
pro (int i = 0; i <10; ++ i)
{
obj.TryAdd (i.ToString (), i.ToString ());
Thread.Sleep (100);
}
}
static void SecondTask (ConcurrentDictionary obj)
{
Závit. Spánek (1000);
foreach (var položka v obj)
{
Console.WriteLine ("Klíč:" + item.Key + "Hodnota:" + item.Value);
Thread.Sleep (100);
}
}
Zde je ukázka, jak můžete spustit výše uvedené dvě metody na dvou instancích úloh současně - jedna pro ukládání hodnot do kolekce a druhá pro čtení hodnot z kolekce.
ConcurrentDictionary obj = new ConcurrentDictionary ();
Task firstTask = Task.Run (() => FirstTask (obj));
Task secondTask = Task.Run (() => SecondTask (obj));
Snaž se
{
Task.WaitAll (firstTask, secondTask);
}
catch (AggregateException ex)
{
// Sem napište vlastní kód pro zpracování výjimky
}
Pokud spustíte výše uvedený kód, výjimka nebude vyvolána, protože kolekce zde je bezpečná pro vlákna.