Programování

Jak pracovat s ConcurrentBag a ConcurrentDictionary v .Net

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.

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