Súbežné kolekcie v .Net sú obsiahnuté vo vnútri priestoru názvov System.Collections.Concurrent a poskytujú uzamknutie a zabezpečenie bezpečných implementácií tried kolekcií. Zbierky bezpečné pre vlákna boli prvýkrát predstavené v .Net 4 a kolekcie boli prvýkrát predstavené ako súčasť .Net Framework 1.0 a boli k dispozícii v mennom priestore System.Collections.
Môžete využiť výhody súbežných kolekcií na prácu s kolekciami, aby ste nemuseli písať akýkoľvek ďalší kód na synchronizáciu vlákien. Môžete sa pozrieť na môj článok o ConcurrentStack a ConcurrentQueue.
ConcurrentBag
ConcurrentBag poskytuje vláknovo bezpečnú zbierku neusporiadanej sady prvkov. Tu je zoznam dôležitých metód triedy ConcurrentBag.
- Pridať (T prvok) - Táto metóda sa používa na pridanie prvku do ConcurrentBag.
- TryPeek (out T) - táto metóda sa používa na načítanie prvku z ConcurrentBag bez jeho odstránenia.
- TryTake (out T) - táto metóda sa používa na načítanie prvku z ConcurrentBag. Táto metóda odstráni položku z kolekcie.
Nasledujúci úryvok kódu ilustruje, ako môžete vytvoriť kolekciu ConcurrentBag a uložiť do nej položky.
ConcurrentBag concurrentBag = nový ConcurrentBag ();
pre (int i = 0; i <10; i ++)
{
concurrentBag.Add (i);
}
Ak by ste chceli vyzdvihnúť položky v zbierke, mali by ste napísať nasledujúci kód:
while (concurrentBag.Count> 0)
{
Prvok Int32;
if (concurrentBag.TryTake (out element))
{
Console.WriteLine (prvok);
}
}
Všimnite si, ako bola použitá metóda TryTake: Vracia true pri úspechu, inak false. Metóda TryTake tiež odstráni položku z kolekcie. Cyklus while pokračuje vo vykonávaní až do času, keď je počet položiek v kolekcii väčší ako nula. Tu je kompletný zoznam kódov pre vašu referenciu.
static void Main (reťazec [] args)
{
ConcurrentBag concurrentBag = nový ConcurrentBag ();
pre (int i = 0; i <10; i ++)
{
concurrentBag.Add (i);
}
while (concurrentBag.Count> 0)
{
Prvok Int32;
if (concurrentBag.TryTake (out element))
{
Console.WriteLine (prvok);
}
}
Console.Read ();
}
ConcurrentDictionary
Slovník je všeobecná zbierka párov kľúč / hodnota. Je to rýchlejšie ako Hashtable, pretože eliminuje režijné náklady spojené s boxom a un-boxom. ConcurrentDictionary je obsiahnutý vo vnútri priestoru názvov System.Collections.Concurrent a predstavuje slovník bezpečný pre vlákna.
Medzi dôležitých členov triedy ConcurrentDictionary patria:
- TryAdd: Táto metóda sa používa na pridanie položky do inštancie ConcurrentDictionary. Upozorňujeme, že táto metóda vyvolá výnimku, ak je kľúč už v kolekcii.
- TryGetValue: Táto metóda sa používa na načítanie položky z kolekcie.
- TryRemove: Táto metóda sa používa na odstránenie položky z kolekcie.
- TryUpdate: Táto metóda sa používa na aktualizáciu konkrétneho kľúča v inštancii ConcurrentDictionary o novú zadanú hodnotu.
Nasledujúci úryvok kódu ukazuje, ako môžete vytvoriť inštanciu ConcurrentDictionary a pridať do nej položky:
ConcurrentDictionary obj = new ConcurrentDictionary ();
obj.TryAdd ("X001", "Toto je prvá hodnota.");
obj.TryAdd ("X002", "Toto je druhá hodnota.");
Ak sa teraz pokúsite pridať ďalšiu položku, ale s rovnakým kľúčom, zlyhá to. Prečítajte si útržok kódu uvedený nižšie.
bool success = obj.TryAdd ("X002", "Toto je tretia hodnota.");
Hodnota premennej success je „false“, pretože pokus o pridanie hodnoty s rovnakým kľúčom zlyhá.
Nasledujúci úryvok kódu ilustruje, ako môžete načítať položku z kolekcie na základe kľúča.
položka reťazca = null;
bool isExist = obj.TryGetValue ("X001", out item);
Ak by ste chceli získať všetky položky v zbierke, môžete namiesto toho použiť nasledujúci útržok kódu.
foreach (var v in obj)
{
Console.WriteLine (v.Key + "---" + v.Value);
}
Nasledujúci útržok kódu ukazuje, ako môžete odstrániť položku z kolekcie.
položka reťazca = null;
bool result = obj.TryRemove ("X001", out item);
Ak by ste chceli odstrániť všetky položky, mohol by sa namiesto toho použiť nasledujúci útržok kódu.
obj.Clear ();
Teraz zvážte nasledujúce dve statické metódy.
static void FirstTask (ConcurrentDictionary obj)
{
pre (int i = 0; i <10; ++ i)
{
obj.TryAdd (i.ToString (), i.ToString ());
Závit. Spánok (100);
}
}
static void SecondTask (ConcurrentDictionary obj)
{
Závit. Spánok (1 000);
foreach (var položka v obj)
{
Console.WriteLine ("Kľúč:" + item.Key + "Hodnota:" + item.Value);
Závit. Spánok (100);
}
}
Tu je príklad, ako môžete vykonať vyššie uvedené dve metódy na dvoch inštanciách úloh súčasne - jedna na ukladanie hodnôt do kolekcie a druhá na čítanie hodnôt z kolekcie.
ConcurrentDictionary obj = new ConcurrentDictionary ();
Úloha firstTask = Task.Run (() => FirstTask (obj));
Úloha secondTask = Task.Run (() => SecondTask (obj));
skús
{
Task.WaitAll (firstTask, secondTask);
}
catch (AggregateException ex)
{
// Sem napíš svoj vlastný kód na spracovanie výnimky
}
Ak spustíte vyššie uvedený kód, výnimka nebude vyvolaná, pretože kolekcia je tu bezpečná pre vlákna.