2. diel - Vlákna - Príklady viacvláknových aplikácií v C# .NET
V dnešnom tutoriále si vyskúšame naprogramovať dve viacvláknové aplikácie, v ktorých sa naučíme vlákna zakladať, pomenovať a spúšťať.
Prvá viacvláknová aplikácia
V našej prvej viacvláknovej aplikácii si ukážeme paralelný beh
dvoch vlákien na striedavej tlači hodnôt 1
a
0
do konzoly. Založme si novú konzolovú aplikáciu.
Metóda TiskJedna()
Do triedy Program
si napíšme metódu pre tlač hodnoty
1
v nekonečnom cykle while:
static void TiskJedna() { while(true) { Console.Write("1 "); } }
Metóda TiskNula()
Podobne si pridajme metódu TiskNula()
, ktorá bude v
nekonečnom cykle tlačiť hodnotu 0
:
static void TiskNula() { while(true) { Console.Write("0 "); } }
Metóda Main()
Nakoniec obe metódy zavolajme v metóde Main()
:
using System;
using System.Threading;
namespace TiskJednaANul
{
class Program
{
static void Main()
{
TiskJedna();
TiskNula();
}
static void TiskJedna()
{
while (true)
{
Console.Write("1 ");
}
}
static void TiskNula()
{
while (true)
{
Console.Write("0 ");
}
}
}
}
Testovanie
Keď aplikáciu spustíme, vidíme neustálu tlač čísla
1
:
Konzolová aplikácia
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ....
Na tlač čísla 0
sa samozrejme nedostalo, pretože sme zostali
zacyklení v metóde TiskJedna()
. Poďme to napraviť pridaním
ďalšieho vlákna.
Úprava metódy Main()
V metóde Main()
vytvoríme nové vlákno pre tlač nuly pomocou
triedy Thread
:
using System;
using System.Threading;
namespace TiskJednaANul
{
class Program
{
static void Main()
{
// Vytvoření vlákna pro 0
Thread vlaknoNula = new Thread(TiskNula);
// Spuštění vlákna vlaknoNula
vlaknoNula.Start();
TiskJedna();
}
static void TiskJedna()
{
while (true)
{
Console.Write("1 ");
}
}
static void TiskNula()
{
while (true)
{
Console.Write("0 ");
}
}
}
}
Testovanie
Po spustení aplikácie teraz v konzole vidíme striedanie tlače čísel
1
a 0
, čo dokazuje paralelný beh oboch vlákien:
Konzolová aplikácia
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...
Poradie tlače 1
a 0
sa bude líšiť
pri každom spustení aplikácie.
Na našej ukážke vidíme, ako operačný systém poskytuje plánovač vlákien. Plánovač vlákien rozhoduje, ktoré vlákno má právo vykonať svoj kód. Plánovač môže prideľovať časové kvantum každému vláknu. Keď jedno vlákno dosiahne koniec svojho časového kvanta, plánovač prepne na iné vlákno.
Pomenovanie vlákien
V rámci vývoja softvéru a práce s vláknami je kľúčové nielen správne riadiť a synchronizovať ich beh, ale tiež mať možnosť jednoznačne ich identifikovať a monitorovať. Jedným z nástrojov na dosiahnutie tejto identifikácie je nastavenie názvu vlákna. Každé vlákno v operačnom systéme má svoje jedinečné identifikačné číslo. Vyskúšame si to na novej konzolovej aplikácii, ktorú si teraz založme.
Metóda MyThreadMethod()
Najprv si do triedy Program
napíšme metódu
MyThreadMethod()
, v ktorej uložíme názov
vlákna z vlastnosti CurrentThread.Name
do premennej
threadName
. Názov vlákna vytlačíme do konzoly:
static void MyThreadMethod() { string threadName = Thread.CurrentThread.Name; Console.WriteLine($"Som vo vlákne s názvom: {threadName}"); }
Metóda Main()
Do metódy Main()
vložíme nasledujúci kód:
using System;
using System.Threading;
namespace JmenaVlaken
{
class Program
{
static void Main()
{
Thread myThread = new Thread(MyThreadMethod);
myThread.Name = "Vedľajšie Vlákno";
myThread.Start();
Thread.CurrentThread.Name = "Hlavné vlákno";
Console.WriteLine($"Som vo vlákne s názvom: {Thread.CurrentThread.Name}");
}
static void MyThreadMethod()
{
string threadName = Thread.CurrentThread.Name;
Console.WriteLine($"Som vo vlákne s názvom: {threadName}");
}
}
}
Najskôr vytvoríme nové vlákno myThread
, v ktorého
konštruktore zavoláme našu metódu MyThreadMethod()
. Do jeho
vlastnosti Name
vložíme názov nášho vlákna
Vedlejší vlákno
a vlákno spustíme. Hlavné vlákno aplikácie
pomenujeme Hlavní vlákno
vo vlastnosti
Thread.CurrentThread.Name
. Nakoniec do konzoly vytlačíme správu
s názvom vlákna.
Testovanie
Po spustení aplikácie uvidíme výpis oboch vlákien:
Konzolová aplikácia
Jsem ve vlákně s názvem: Hlavní vlákno
Jsem ve vlákně s názvem: Vedlejší Vlákno