Lekce 3 - Vlákna - Uspání, blokování a stavy vláken ve VB.NET
V minulé lekci, Vlákna - Příklady vícevláknových aplikací ve VB.NET, jsme si naprogramovali dvě vícevláknové aplikace, ve kterých jsme se naučili vlákna zakládat, pojmenovat a spouštět.
V dnešním VB.NET tutoriálu se naučíme základy
synchronizace vláken. Ukážeme si, jak vlákna
uspat a blokovat. Představíme si třídu
Thread a seznámíme se se stavy vláken. Vše si
ukážeme na funkčních příkladech.
Uspaní vláken
V rámci práce s vícevláknovým prostředím nabízí třída
Thread užitečné metody pro řízení toku vláken, mezi nimiž
patří metoda Sleep(). Metoda Sleep() na třídě
Thread se používá pro dočasné pozastavení
běhu aktuálního vlákna na definovanou dobu v
milisekundách. Typickým použitím je simulace čekání na určitou
událost, nebo zpomalení běhu programu.
Pro zápis doby uspání můžeme v parametru metody
Sleep() využít strukturu TimeSpan.
Metoda Sleep()
Uspání vlákna na dobu 1 hodiny provedeme takto:
Thread.Sleep(3600000)
Metoda Sleep() s
TimeSpan
S využitím struktury TimeSpan uspíme vlákno na stejnou dobu
takto:
Thread.Sleep(TimeSpan.FromHours(1))
Blokování vláken
Další užitečnou metodou třídy Thread je metoda
Join(). Metoda Join() blokuje volající vlákno,
dokud se vlákno reprezentované instancí typu Thread neukončí.
Metoda umožňuje synchronizaci vláken a čekání na
dokončení určitého vlákna před pokračováním ve zpracování hlavního
vlákna. To je užitečné v situacích, kdy potřebujeme vyčkat na dokončení
nějaké operace.
Příklad
Nejlépe to uvidíme na příkladu. Založme si novou konzolovou aplikaci.
Budeme pracovat pouze v Module1.vb.
Proměnná hodnota
Nejdříve si nad metodu Main() vložme proměnou
hodnota, kterou naplňme hodnotou 0:
Dim hodnota As Integer = 0
Metoda PrictiJedna()
Pod metodu Main() si napišme první metodu, kterou budeme
volat, metodu PrictiJedna(). V metodě implementujeme zvýšení
hodnoty proměnné hodnota o hodnotu 1 a její výpis
do konzole:
Sub PrictiJedna() For i As Integer = 1 To 10 hodnota += 1 Next Console.WriteLine("Hodnota proměnné: {0}", hodnota) End Sub
Metoda OdectiJedna()
Podobně implementujeme metodu OdectiJedna(). V metodě tedy
snížíme hodnotu proměnné hodnota o 1 a vypíšeme
ji do konzole:
Sub OdectiJedna() For i As Integer = 1 To 10 hodnota -= 1 Next Console.WriteLine("Hodnota proměnné: {0}", hodnota) End Sub
Metoda Main()
Pomocné metody implementované máme. Můžeme se tedy vrhnout na
dokončení programu v metodě Main():
Imports System.Threading
Module Module1
    Dim hodnota As Integer = 0
    Sub Main()
        Dim pricteniThread As New Thread(AddressOf PrictiJedna)
        Dim odecitaniThread As New Thread(AddressOf OdectiJedna)
        pricteniThread.Start()
        pricteniThread.Join()
        odecitaniThread.Start()
        odecitaniThread.Join()
        Console.WriteLine("Výsledek: {0}", hodnota)
        Console.ReadKey()
    End Sub
    Sub PrictiJedna()
        For i As Integer = 1 To 10
            hodnota += 1
        Next
        Console.WriteLine("Hodnota proměnné: {0}", hodnota)
    End Sub
   Sub OdectiJedna()
       For i As Integer = 1 To 10
           hodnota -= 1
       Next
       Console.WriteLine("Hodnota proměnné: {0}", hodnota)
   End Sub
End ModuleVytvoříme dvě vlákna. Vlákno:
- pricteniThread, v jehož konstruktoru zavoláme metodu- PrictiJedna(),
- odecitaniThread, v jehož konstruktoru zavoláme metodu- OdectiJedna().
Obě vlákna spustíme a poté na nich zavoláme metodu Join().
Nakonec do konzole vytiskneme výslednou hodnotu proměnné
hodnota.
Testování
Po spuštění aplikace vidíme, jak se hodnota proměnné
hodnota mění:
Konzolová aplikace
Hodnota proměnné: 10
Hodnota proměnné: 0
Výsledek: 0
Stavy vláken
Podívejme se na některé ze stavů, které vlákno může nabývat. Stav
vlákna lze zjistit pomocí jeho vlastnosti ThreadState, která je
výčtovým typem sestávajícím z jedné nebo více z
následujících hodnot:
- Running– Vlákno je v běhu, provádí svůj kód.
- StopRequested– Bylo požádáno o zastavení vlákna, ale ještě nebylo zastaveno.
- SuspendRequested– Bylo požádáno o pozastavení vlákna, ale ještě nebylo pozastaveno.
- Background– Vlákno je nastaveno jako pozadí.
- Unstarted– Vlákno bylo vytvořeno, ale ještě nebylo spuštěno.
- Stopped– Vlákno bylo zastaveno.
- WaitSleepJoin– Vlákno čeká v režimu spánku nebo na spojení.
- Suspended– Vlákno bylo pozastaveno.
- AbortRequested– Bylo požádáno o zrušení vlákna, ale ještě nebylo zrušeno.
- Aborted– Vlákno bylo zrušeno.
Příklad
Ukažme si výpis stavů vláken na příkladu.
Metoda Counting()
V konzolové aplikaci si napíšeme tuto metodu:
Sub Counting() For i As Integer = 0 To 4 Console.WriteLine(i) Thread.Sleep(500) Next End Sub
V metodě Counting() provádíme číslování od 0
do 4 s výpisem čísel. Mezi každý výpis vkládáme pauzu
trvající 500 milisekund.
Metoda Main()
Do metody Main() přidáme následující kód:
Imports System.Threading
Module Module1
    Sub Main()
        Dim countingThread As New Thread(AddressOf Counting)
        Console.WriteLine("Stav vlákna po vytvoření: {0}", countingThread.ThreadState)
        countingThread.Start()
        Console.WriteLine("Stav vlákna po spuštění: {0}", countingThread.ThreadState)
        Thread.Sleep(100)
        Console.WriteLine("Stav vlákna po chvilce čekání: {0}", countingThread.ThreadState)
        countingThread.Join()
        Console.WriteLine("Stav vlákna po dokončení: {0}", countingThread.ThreadState)
        Console.ReadKey()
    End Sub
    Sub Counting()
        For i As Integer = 0 To 4
            Console.WriteLine(i)
            Thread.Sleep(500)
        Next
    End Sub
End ModuleV metodě Main() vytváříme nové vlákno pomocí třídy
Thread a jejího konstruktoru, kterému předáváme metodu
Counting(). Poté vypisujeme stav vlákna pomocí vlastnosti
ThreadState v různých bodech životního cyklu vlákna.
Stav vlákna je zajímavý pouze ve scénářích ladění. Kód by nikdy neměl používat stav vlákna k synchronizaci aktivit vláken.
Testování
Spuštěním kódu uvidíme výpis stavů vláken:
Konzolová aplikace
Stav vlákna po vytvoření: Unstarted
Stav vlákna po spuštění: Running
0
Stav vlákna po chvilce čekání: WaitSleepJoin
1
2
3
4
Stav vlákna po dokončení: Stopped
V následujícím kvízu, Kvíz - Úvod, synchronizace a stavy vláken ve VB.NET, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.
 
				
