IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

2. diel - Vlákna - Príklady viacvláknových aplikácií vo VB.NET

V dnešnom VB.NET tutoriále si vyskúšame naprogramovať dve viacvláknové aplikácie, v ktorých sa naučíme vlákna zakladať, pomenovať a spúšťať.

Tlač jednotiek a nul

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:

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 ...

Založme si novú konzolovú aplikáciu s názvom TiskJednicek_A_Nul.

Metóda TiskniJednicky()

Do triedy Program si napíšme metódu pre tlač hodnoty 1 v nekonečnom cykle while:

Sub TiskniJednicky()
    While True
        Console.Write("1 ")
    End While
End Sub

Metóda TiskNula()

Podobne si pridajme metódu TiskNula(), ktorá bude v nekonečnom cykle tlačiť hodnotu 0:

Sub TiskNula()
    While True
        Console.Write("0 ")
    End While
End Sub

Metóda Main()

Nakoniec obe metódy zavolajme v metóde Main():

Module Module1
    Sub Main()
        TiskniJednicky()
        TiskNula()
    End Sub

    ...
End Module

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 TiskniJednicky(). 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:

Imports System.Threading

Module Module1
    Sub Main()
        Dim vlaknoNula As New Thread(AddressOf TiskNula)
        vlaknoNula.Start()

        TiskniJednicky()
    End Sub

    ...
End Module

Najskôr vytvoríme nové vlákno vlaknoNula, v ktorého konštruktore zavoláme našu metódu TiskNula(). Vlákno vlaknoNula potom spustíme. Nakoniec zavoláme metódu TiskniJednicky(), ktorá bude v nekonečnom cykle tlačiť hodnotu 1 do konzoly.

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.

V ukážke vidíme, ako operačný systém poskytuje plánovač vlákien. Plánovač vlákien rozhoduje o tom, 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.

Úlohy

Predstavme si aplikáciu, ktorá spracováva úlohy v aplikácii. Založme si konzolovú aplikáciu s názvom Ukoly. V našej aplikácii bude:

  • Prvé vlákno zodpovedné za načítanie úloh ("Načítacie vlákno").
  • Druhé vlákno bude vykonávať načítané úlohy ("Spracovávacie vlákno").
Výstup z aplikácie bude vyzerať takto:
Konzolová aplikácia
[Načítací vlákno pro úkoly] Načítání nových úkolů...
[Zpracovávací vlákno pro úkoly] Zpracovávání úkolů...
[Načítací vlákno pro úkoly] Nové úkoly načteny.
[Načítací vlákno pro úkoly] Přiřazování úkolu: Úkol 1: Implementace nového rozhraní.
[Zpracovávací vlákno pro úkoly] Zpracovávání úkolu 1.
[Načítací vlákno pro úkoly] Přiřazování úkolu: Úkol 2: Testování aplikace.
[Načítací vlákno pro úkoly] Přiřazování úkolu: Úkol 3: Oprava chyb v kódu.
[Načítací vlákno pro úkoly] Všechny úkoly přiřazeny.
[Zpracovávací vlákno pro úkoly] Zpracovávání úkolu 2.
[Zpracovávací vlákno pro úkoly] Zpracovávání úkolu 3.
[Zpracovávací vlákno pro úkoly] Všechny úkoly zpracovány.

Budeme pracovať iba v module Module1.vb.

Pole assignedTasks

Nad metódu Main() deklarujeme pole assignedTasks():

Dim assignedTasks() = {"Úkol 1: Implementace nového rozhraní", "Úkol 2: Testování aplikace", "Úkol 3: Oprava chyb v kódu"}

Metóda NactiUkoly()

V tejto metóde implementujeme načítanie nových úloh:

Sub NactiUkoly()
    Dim threadName As String = Thread.CurrentThread.Name
    Console.WriteLine($"[{threadName}] Načítanie nových úloh...")
    Thread.Sleep(2000)
    Console.WriteLine($"[{threadName}] Nové úlohy načítané.")


    For Each task As String In assignedTasks
        Console.WriteLine($"[{threadName}] Priraďovanie úlohy: {task}")
        Thread.Sleep(1000)
    Next

    Console.WriteLine($"[{threadName}] Všetky úlohy priradené")
End Sub

Najprv si uložíme názov vlákna do premennej threadName pomocou vlastnosti Thread.CurrentThread.Name. Potom vytlačíme názov vlákna do konzoly spolu s informáciami o priebehu načítavania a priraďovania úloh.

Metóda ZpracujUkoly()

V tejto metóde budeme načítané úlohy spracovávať:

Sub ZpracujUkoly()
    Dim threadName As String = Thread.CurrentThread.Name
    Console.WriteLine($"[{threadName}] Spracovávanie úloh:")

    For i As Integer = 1 To assignedTasks.Length
        Console.WriteLine($"[{threadName}] Spracovávanie úlohy {i}")
        Thread.Sleep(2000)
    Next

    Console.WriteLine($"[{threadName}] Všetky úlohy spracované")
End Sub

Najprv si uložíme názov vlákna do premennej threadName pomocou vlastnosti Thread.CurrentThread.Name. Potom vytlačíme názov vlákna do konzoly spolu s informáciami o priebehu spracovania úloh.

Metóda Main()

A nakoniec v metóde Main() obe vlákna spustíme:

    Sub Main()

        Dim nacitaciVlakno As New Thread(AddressOf NactiUkoly)
        nacitaciVlakno.Name = "Načítacie vlákno pre úlohy"
        nacitaciVlakno.Start()

        Dim zpracovavaciVlakno As New Thread(AddressOf ZpracujUkoly)
        zpracovavaciVlakno.Name = "Spracovávacie vlákno pre úlohy"
        zpracovavaciVlakno.Start()

        Console.ReadKey()

    End Sub

V metóde vytvoríme vlákna nacitaciVlakno a zpracovavaciVlakno. Do vlastnosti Name vložíme ich názvy. A potom už len metódou Start() obe vlákna spustíme.

Testovanie

Po spustení aplikácie uvidíme výpis práce oboch vlákien:

Konzolová aplikácia
[Načítací vlákno pro úkoly] Načítání nových úkolů...
[Zpracovávací vlákno pro úkoly] Zpracovávání úkolů
[Načítací vlákno pro úkoly] Nové úkoly načteny
[Načítací vlákno pro úkoly] Přiřazování úkolu: Úkol 1: Implementace nového rozhraní
[Zpracovávací vlákno pro úkoly] Zpracovávání úkolu 1
[Načítací vlákno pro úkoly] Přiřazování úkolu: Úkol 2: Testování aplikace
[Načítací vlákno pro úkoly] Přiřazování úkolu: Úkol 3: Oprava chyb v kódu
[Načítací vlákno pro úkoly] Všechny úkoly přiřazeny
[Zpracovávací vlákno pro úkoly] Zpracovávání úkolu 2
[Zpracovávací vlákno pro úkoly] Zpracovávání úkolu 3
[Zpracovávací vlákno pro úkoly] Všechny úkoly zpracovány

V budúcom dieli, Vlákna v VB.NET - Sleep, Join a lock , sa pozrieme na uspávanie vlákien, ich spájanie a základy synchronizácie.


 

Všetky články v sekcii
Paralelné programovanie a viacvláknové aplikácie v VB.NET
Preskočiť článok
(neodporúčame)
Vlákna v VB.NET - Sleep, Join a lock
Článok pre vás napísal Stanislav Zita
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Aktivity