Programování

Jak pracovat s BlockingCollection v C #

Zvažte scénář, kdy by více vláken četlo a zapisovalo do fronty. Přesněji řečeno, ve stejném okamžiku můžete mít více výrobců, kteří ukládají data, a více spotřebitelů, kteří je načítají ze společného úložiště dat. Proto byste potřebovali vhodný synchronizační mechanismus, abyste mohli synchronizovat přístup k těmto datům.

Tady je přesně místo, kde třída BlockingCollection přijde na záchranu. Ačkoli existuje mnoho dalších způsobů, tato třída poskytuje jeden z nejúčinnějších způsobů synchronizace přístupu k vašim datům. Třída BlockingCollection patří do oboru názvů System.Collections.Concurrent.

Co je BlockingCollection?

BlockingCollection je kolekce bezpečná pro vlákna, ve které můžete mít více vláken současně přidávat a odebírat data. Je zastoupena v .Net prostřednictvím třídy BlockingCollection; tuto třídu můžete použít k implementaci vzoru producent-spotřebitel.

Ve vzoru producent-spotřebitel máte dvě odlišné komponenty, které běží na dvou různých vláknech. Patří mezi ně komponenta producenta, která produkuje některá data, která jsou odesílána do fronty, a spotřebitel, který spotřebovává data, která jsou uložena ve frontě. Když používáte BlockingCollection, můžete určit omezenou kapacitu a typ kolekce, kterou chcete použít.

Typ BlockingCollection funguje jako obálka nad instancí typu IProducerConsumerCollection. Jinými slovy funguje jako obálka nad jinou kolekcí, která zase implementuje rozhraní IProducerConsumerCollection. Jako příklad lze třídy ConcurrentBag, ConcurrentQueue a ConcurrentStack použít s BlockingCollection, protože všechny implementují rozhraní IProducerConsumerCollection.

Všimněte si, že rozhraní IProducerConsumerCollection obsahuje deklaraci metod, které lze použít pro práci s kolekcemi bezpečnými pro vlákna. MSDN uvádí: "Definuje metody pro manipulaci s kolekcemi bezpečnými pro vlákna určenými pro použití producentem / spotřebitelem. Toto rozhraní poskytuje jednotné zastoupení pro kolekce producent / spotřebitel tak, aby abstrakce na vyšší úrovni, jako je System.Collections.Concurrent.BlockingCollection, mohly kolekci používat jako základní mechanismus ukládání. “

Následující fragment kódu ukazuje, jak můžete vytvořit instanci BlockingCollection řetězců.

var blockingCollection = new BlockingCollection ();

Při použití BlockingCollection můžete do kolekce přidat data buď pomocí Add metody, nebo TryAdd metody. Pojďme nyní pochopit rozdíl mezi těmito dvěma metodami.

Data BlockingCollection = nová BlockingCollection (boundedCapacity: 3);

data.Add (1);

data.Add (2);

data.Add (3);

data.Add (4); // To by blokovalo, dokud nebude položka odebrána ze sbírky.

Všimněte si, jak jsme určili boundedCapacity při vytváření instance BlockingCollection, jak je ukázáno ve fragmentu kódu uvedeném výše. Toto je určeno k označení omezené velikosti instance kolekce.

Můžete také použít metodu TryAdd k přidání položky do instance BlockingCollection. V této metodě můžete použít hodnotu časového limitu. Pokud operace přidání selže ve stanoveném čase, vrátí metoda TryAdd hodnotu false. Následující fragment kódu ukazuje, jak můžete využít metodu TryAdd k přidání položky do instance BlockingCollection.

Data BlockingCollection = nová BlockingCollection (boundedCapacity: 3);

data.Add (1);

data.Add (2);

data.Add (3);

if (data.TryAdd (4, TimeSpan.FromMilliseconds (100)))

{

Console.WriteLine („Do kolekce byla úspěšně přidána nová položka.“);

}

jiný

{

Console.WriteLine („Nepodařilo se přidat novou položku do kolekce.“);

}

Chcete-li odebrat položku z BlockingCollection, můžete použít metodu Take nebo TryTake. Všimněte si, že metoda Take blokuje, pokud v kolekci nejsou žádné položky, a odblokuje se, jakmile se do kolekce přidá nová položka. Metodu TryTake lze také použít k odebrání položky z instance BlockingCollection. U této metody můžete určit hodnotu časového limitu, aby metoda blokovala (dokud neuplyne zadaný čas), dokud nebude do kolekce přidána položka. Pokud během této doby (zadaný časový limit) nelze položku z kolekce odebrat, vrátí metoda TryTake hodnotu false.

Následující fragment kódu ukazuje, jak lze TryTake metodu použít k odebrání položky z instance typu BlockingCollection.

int položka;

while (data.TryTake (out item, TimeSpan.FromMilliseconds (100))))

{

Console.WriteLine (položka);

}

Zde je kompletní seznam kódů pro vaši referenci. Tento program ukazuje, jak můžete použít BlockingCollection k přidávání a odebírání položek do az kolekce.

třídní program

   {

soukromá statická data BlockingCollection = nová BlockingCollection ();

private static void Producer ()

       {

pro (int ctr = 0; ctr <10; ctr ++)

           {

data.Add (ctr);

Thread.Sleep (100);

           }

       }

private static void Consumer ()

       {

foreach (var položka v data.GetConsumingEnumerable ())

           {

Console.WriteLine (položka);

           }

       }

static void Main (řetězec [] args)

       {

var producent = Task.Factory.StartNew (() => producent ());

var consumer = Task.Factory.StartNew (() => Consumer ());

Console.Read ();

       }

   }

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