reklama

Poznáváme C# a Microsoft. NET 52. díl – ThreadPool

Dnešní díl navazuje na použití vláken, které je již několik dílů seriálů probíráno a bude se zabývat zajímavou cestou k jednodušší implementaci asynchronních operací prostředí .NET.

Vlákna typu démon

Jelikož se v tomto díle budu zaobírat použitím třídy ThreadPool, dozvíme se co jsou vlákna typu démon a jakým způsobem tyto vlákna vytvořit, protože to s využitím třídy ThreadPool úzce souvisí.

Vlákna typu démon nejsou nic složitého ani nic nového, co by se poprvé objevilo s příchodem platformy .NET. Vlákna můžeme s určitého pohledu dělit na dva druhy, kde prvním jsou vlákna hlavní a druhým jsou právě vlákna typu démon. Hlavní vlákna zařizují hlavní operace aplikace, a pokud je alespoň jedno hlavní vlákno běžící, aplikace neskončí.

Přesným opakem jsou vlákna typu démon, která jsou určena k provádění pomocných operací jakoby „na pozadí“ a tyto operace nejsou natolik důležité, aby kvůli nim nemohla aplikace skončit. To ve výsledku znamená, že pokud skončí poslední běžící hlavní vlákno, tak je běh aplikace ukončen bez ohledu na to, kolik ještě běží vláken typu démon.

A jak takováto vlákna v prostředí .NET vytvořit, ukazuje následující zdrojový kód.

/// <summary>
/// Priklad na pouziti vlaken typu demon
/// </summary>
internal class BackgroundThreads
{
  internal static void Run()
  {
    Thread lThread = new Thread(new ThreadStart(DaemonMethod));
    //nastavime vlaknu, ze je demon
    lThread.IsBackground = true;
    lThread.Start();
    System.Windows.Forms.MessageBox.Show("Pro skonceni behu hlavniho vlakna stisknete OK");
  }
   
  static void DaemonMethod()
  {
    for (char ch = `a`; ch < `z`; ch++)
    {
      Console.WriteLine("DaemonMethod : " + ch);
      Thread.Sleep(400);
    }            
  }
}

Je to velmi snadné, protože ve skutečnosti využijeme pouze instanční vlastnost třídy Thread, kterou je IsBackground, které pokud nastavíme hodnotu true, tak s ní .NET runtime bude nakládat jako s vláknem typu démon. Takže pokud pokud je běh hlavního vlákna dokončen, tak bez ohledu na to jestti námi spuštěné druhé vláknoještě běží je aplikace ukončena.

Použití třídy ThreadPool

Během několika předchozích dílů jsme se zabývali vytvářením nových vláken, jejich spouštěním a v neposlední řadě, také jejich řízením. .NET framework nám umožňuje se velké části těchto operací nevěnovat a nechat ji na starost běhovému prostředí. Samozřejmě není vždy možné se těmto operacím nevěnovat, protože jistě narazíte na spoustu situací, ve kterých bude potřeba si řízení vláken obstarat způsobem, který jsem popisoval v předchozích dílech. Ale v případě jednoduchých situací, můžeme ponechat detaily na běhovém prostředí a směle využít třídu ThreadPool.

Třída ThreadPool nám reprezentuje pool, nebo jinými slovy,“zásobník” vláken, které řídí běhové prostředí a my pomocí rozhraní této třídy běhovému prostředí pouze sdělujeme, že bychom chtěli určitou metodu zavolat asynchronně, jakmile to bude možné. Možné to bude v případě, že se v poolu nachází nějaké vlákno, které je volné, což znamená, že právě nezpracovává nějakou operaci.

ThreadPool je jedinečný pro proces CLR, ve kterém jsou obsaženy aplikační domény a to mimo jiné umožňuje běhovému prostředí optimalizovat použití vláken z poolu jednotlivými .NET aplikacemi. To pro nás znamená, že v mnoha případech, kdy potřebujeme implementovat provádění asynchronních operací, představuje použití ThreadPoolu nejjednodušši a nejlepší cestu.

Po teoretickém představení ThreadPoolu se nyní podívejme na jeho použití v praxi.

/// <summary>
/// Pouziti tridy ThreadPool pro snadnejsi praci s vlakny
/// </summary>
internal class ThreadPoolExample
{
  internal static void Run()
  {
    WaitCallback lCallBack = new WaitCallback(ThreadMethod);
    //sdelime systemu, ze metodu asociovanou
    //s predanym delegatem ma spustit asynchronne
    ThreadPool.QueueUserWorkItem(lCallBack, "At zije ThreadPool :-)");
    //vyckame, nez je systememem spusteno
    //druhe vlakno a provede svou praci
    Thread.Sleep(1000);
    Console.WriteLine("Hlavni vlakno konci svou cinnost");
  }

  static void ThreadMethod(object data)
  {
    Console.WriteLine("Metoda ThreadMethod byla zavolana s daty : {0}", data);
  }
}

Použití třídy ThreadPool pro spuštění metody asynchronně v jiném vláknu je velmi jednoduché, což je také jejím posláním (odstítnit od problematiky řízení vláken, aby se mohl vývojář věnovat implementaci aplikační logiky). K realizaci vyčlenení vlastního vlákna pro provedení operace, pouze využijeme metodu QueueUserWorkItem, která přijímá instanci delegáta WaitCallBack, který předepisuje rozhraní metody na návratový typ void a jeden vstupní parametr obecného typu object, jež se používá k předání dat metodě spuštěné vláknem. K předání dat do metody asociované s delegátem WaitCallBack použijeme druhý parametr metody QueueUserWorkItem. V případě našeho příkladu jsou metodě spouštěné v separátním vláknu předána data v podobě řetězce "At zije ThreadPool :-)".

Možná se divíte, proč je v příkladu použita metoda Sleep pro počkání na provedení asynchronních operací vykonávaných metodou ThreadMethod. Je tomu tak z důvodu, že by byla aplikace ukončena dříve, než by běhové prostředí zařídilo vykonání metody ThreadMethod v novém vlákně a to protože jsou všechna vlákna spouštěná pomocí třídy ThreadPool typu démon, tudíž se na dokončení činnosti, kterou tato vlákna vykonávají, vůbec nečeká.

Informace o thread poolu

Jistě mnohé z vás napadlo, kolik je tedy vlastně v poolu běhového prostředí k dispozici vláken nebo jaký je maximální počet vláken, které mohou být v poolu. Odpověď na obě tyto otázky vám zodpoví metody GetAvailableThreads a GetMaxThreads, které jsou použity v následujícím příkladu.

/// <summary>
/// Ukazka zjisteni informaci o poctu vlaken ThreadPoolu
/// </summary>
internal class ThreadPoolInfo
{
  internal static void Run()
  {
    int lAvailThreads;
    int lAvailIOThreads;
    int lMaxThreads;
    int lMaxIOThreads;
    ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadMethod));
    //pockame nez runtime spusti vlakno
    Thread.Sleep(300);
    ThreadPool.GetAvailableThreads(out lAvailThreads,out lAvailIOThreads);
    ThreadPool.GetMaxThreads(out lMaxThreads, out lMaxIOThreads);
    Console.WriteLine("Pocet volnych vlaken : {0}, Pocet vlaken pro provadeni asynn. IO operaci : {1}", lAvailThreads, lAvailIOThreads);
    Console.WriteLine("Max. pocet vlaken : {0}, Max.pocet vlaken pro provadeni asynn. IO operaci : {1}", lMaxThreads, lMaxIOThreads);
    Thread.Sleep(1000);
    Console.WriteLine("Cinnost hlavniho vlakna skoncila");
  }

  static void ThreadMethod(object data)
  {
    Console.WriteLine("Metoda ThreadMethod byla zavolana.");
    Thread.Sleep(1000);
  }
}

Nás hlavně zajímá první údaj vracený výstupním parametrem obou metod, který říká kolik je v danou chvíli k dispozici volných vláken respektive, jaký je maximální počet vláken. Jelikož je v příkladu spuštěna jedna asychronní úloha, tak by se měl údaj o max. počtu vláken a počtu vláken k dipozici lišit.

Příklady ke článku si můžete stáhnout zde.

Témata článku: Software, Microsoft, Windows, Programování, Demon, IO, Pool

1 komentář

Nejnovější komentáře

  • Pavel Polívka 24. 11. 2007 13:47:09
    Programovou oflline verzi seriálu naleznete ke stažení na...
reklama
Určitě si přečtěte

UPC překopli páteřní kabel. V Brně i druhý den nejede internet ani kabelovka

UPC překopli páteřní kabel. V Brně i druhý den nejede internet ani kabelovka

** V Brně byl velký výpadek služeb UPC ** Důvodem je překopnutý páteřní kabel ** V některých lokalitách služby stále nefungují

5.  12.  2016 | Jakub Čížek | 103

17 expertek Microsoftu předpovědělo rok 2027. Splní se alespoň něco?

17 expertek Microsoftu předpovědělo rok 2027. Splní se alespoň něco?

** Zmizí klasické vyhledávače ** Budeme programovat buňky ** Kvantové počítače překonají šifry

6.  12.  2016 | Jakub Čížek | 36

11 tipů na dobrý stolní počítač: od základu po herní mašiny

11 tipů na dobrý stolní počítač: od základu po herní mašiny

** Postavte si stolní počítač! Máme pro vás 11 vzorových sestav s rozpisem komponent ** Většina tipů cílí na hráče, věnujeme se ale i základnímu PC a počítačům na střih videa ** Nadělte si nový počítač třeba pod stromeček

5.  12.  2016 | Adam Kahánek | 74

Nejlepší notebooky nad 20 tisíc: poradíme, které teď chcete

Nejlepší notebooky nad 20 tisíc: poradíme, které teď chcete

** V notebooku s cenou nad 20 tisíc nesmí chybět kvalitní displej a rychlé úložiště ** Za dalších deset tisíc můžete dostat navíc styl nebo výkonnější komponenty ** Vybírat můžete z různých velikostí i konstrukcí

8.  12.  2016 | Stanislav Janů | 85


reklama