Programovanie

Ako pracovať s ConcurrentBag a ConcurrentDictionary v .Net

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.

$config[zx-auto] not found$config[zx-overlay] not found