Snížení počtu vláken   otázka

VB.NET, Algoritmy, Threading

Zdravím všechny a prosím o radu jak snížit počet vláken na max 2.

Zjednodušil jsem to:

Public Class Form1
    Dim aktivni(7) As Boolean
    Dim casi(7, 1) As Integer 'vstup třeba ze scrollbarů pro každou proměnou

    Dim vlakno0 As New Threading.Thread(AddressOf vl0)
    Dim vlakno1 As New Threading.Thread(AddressOf vl1)
    Dim vlakno2 As New Threading.Thread(AddressOf vl2)
    Dim vlakno3 As New Threading.Thread(AddressOf vl3)
    Dim vlakno4 As New Threading.Thread(AddressOf vl4)
    Dim vlakno5 As New Threading.Thread(AddressOf vl5)
    Dim vlakno6 As New Threading.Thread(AddressOf vl6)
    Dim vlakno7 As New Threading.Thread(AddressOf vl7)

    Dim write As New Threading.Thread(AddressOf wr)

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        write.Start()
    End Sub
    Sub wr()
        vlakno0.Start()
        vlakno1.Start()
        vlakno2.Start()
        vlakno3.Start()
        vlakno4.Start()
        vlakno5.Start()
        vlakno6.Start()
        vlakno7.Start()

dokola:
        If aktivni(0) = True Then
           'neco
        End If
        If aktivni(1) = True Then
          'neco
        End If
        If aktivni(2) = True Then
           'neco
        End If
        If aktivni(3) = True Then
          'neco
        End If
        If aktivni(4) = True Then
          'neco
        End If
        If aktivni(5) = True Then
          'neco
        End If
        If aktivni(6) = True Then
         'neco
        End If
        If aktivni(7) = True Then
         'neco
        End If
        GoTo dokola
    End Sub
    Sub vl0()
start:
        aktivni(0) = True
        Threading.Thread.Sleep(casi(0, 0))
        aktivni(0) = False
        Threading.Thread.Sleep(casi(0, 1))
        GoTo start
    End Sub
    Sub vl1()
start:
        aktivni(1) = True
        Threading.Thread.Sleep(casi(1, 0))
        aktivni(1) = False
        Threading.Thread.Sleep(casi(1, 1))
        GoTo start
    End Sub
    Sub vl2()
start:
        aktivni(2) = True
        Threading.Thread.Sleep(casi(2, 0))
        aktivni(2) = False
        Threading.Thread.Sleep(casi(2, 1))
        GoTo start
    End Sub
  
'... atd až do 8 vlákna

    Sub vl7()
start:
        aktivni(7) = True
        Threading.Thread.Sleep(casi(7, 0))
        aktivni(7) = False
        Threading.Thread.Sleep(casi(7, 1))
        GoTo start
    End Sub
End Class

V tomto stavu bere 50% z dvoujádrového procesoru.

Jedno vlákno neustále zpracovává výstupy z dalších 8 vláken což značně zatěžuje procesor.

Děkuji za případné rady

Používám VB.NET 2010 Express

nahlásit spamnahlásit spam -1 / 3 odpovědětodpovědět

Jak vám na takovou hovadinu může někdo odpovědět, když vůbec není jasné, co těch 8 vláken dělá??? (respektive z toho co zde je je vidět, že vlákna pouze nastavují proměnné a mezi tím se flákají a tedy vůbec nejsou potřeba)

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Každé z těch 8 vláken nastaví proměnou, počká určitý čas a nestaví tu samou proměnou zpět a opět počká určitý čas. Jiné vlákno tyto proměnné neustále vyhodnocuje a naráz zpracuje. Otázka zní jak to zjednodušit, aby se proměné po určítém času přepsaly a všech 8 proměných naráz zpracovalo. Chci to aplikovat na ovládání pinů LPT portu.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Toto je uměle vymyšlený příklad, který nijak zjednodušit nelze. Zjednodušit by to možná šlo, kdyby ta vlákna dělala něco smysluplného.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

http://www.codeproject.com/KB/vb/PortAcc... podle tohoto jsem stvořil toto:

Public Class Form1
    Inherits Form
    Dim sum As Byte
    Public intAddress As Integer
    Public intVal2Write As Integer
    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        'Declare variables to store read information and Address
        'values
        Dim intAddress As Integer, intReadVal As Integer
        If ComboBox1.Text = Nothing Then
        Else
            'Get the address from the Textbox
            intAddress = Convert.ToInt32(ComboBox1.Text)
            'Read the corresponding value and store
            intReadVal = porting.Inp(intAddress)
            TextBox2.Text = intReadVal.ToString()
        End If
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        bintodec()
        'Dim intAddress As Integer, intVal2Write As Integer
        'Get the address from the Textbox
        If Not ComboBox1.Text = Nothing Then
            intAddress = Convert.ToInt16(ComboBox1.Text)
            'Read the corresponding value and store
            intVal2Write = Convert.ToString(sum)
            'porting is the name of the module
            porting.Out(intAddress, intVal2Write)
        End If
        sum = 0
    End Sub
    Sub bintodec()
        If CheckBox1.Checked = True Then
            sum = 1
        End If
        If CheckBox2.Checked = True Then
            sum = sum + 2
        End If
        If CheckBox3.Checked = True Then
            sum = sum + 4
        End If
        If CheckBox4.Checked = True Then
            sum = sum + 8
        End If
        If CheckBox5.Checked = True Then
            sum = sum + 16
        End If
        If CheckBox6.Checked = True Then
            sum = sum + 32
        End If
        If CheckBox7.Checked = True Then
            sum = sum + 64
        End If
        If CheckBox8.Checked = True Then
            sum = sum + 128
        End If
        Label3.Text = CStr(sum)
    End Sub

a následně toto:

Public Class Form1
    Inherits Form
    Dim t As New Threading.Thread(AddressOf write)
    Dim sum As Byte
    Public intAddress As Integer
    Public intVal2Write As Integer

    Private Sub HScrollBar1_Scroll(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ScrollEventArgs) Handles HScrollBar1.Scroll
        Label10.Text = (0 + HScrollBar2.Value) / HScrollBar1.Value
        Label11.Text = (100 - HScrollBar2.Value) / HScrollBar1.Value
        Label12.Text = CStr(CStr(HScrollBar2.Value) + "%")
    End Sub
    Private Sub HScrollBar2_Scroll(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ScrollEventArgs) Handles HScrollBar2.Scroll
        Label10.Text = (0 + HScrollBar2.Value) / HScrollBar1.Value
        Label11.Text = (100 - HScrollBar2.Value) / HScrollBar1.Value
        Label12.Text = CStr(CStr(HScrollBar2.Value) + "%")
    End Sub

    Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
            t.Start(
    End Sub
    Sub write()
start:

        sum = 64

        intAddress = Convert.ToInt16(1912)
        'Read the corresponding value and store
        intVal2Write = Convert.ToString(sum)
        'porting is the name of the module
        porting.Out(intAddress, intVal2Write)

        Threading.Thread.Sleep(Label10.Text)

        sum = 0
        intAddress = Convert.ToInt16(1912)
        'Read the corresponding value and store
        intVal2Write = Convert.ToString(sum)
        'porting is the name of the module
        porting.Out(intAddress, intVal2Write)
        Threading.Thread.Sleep(Label11.Text)
        GoTo start
    End Sub


End Class

Výsledek je zapínaní/vypínaní pinu po uplynutí doby nastavené pomocí scrollbarů.

Bohužel je to pouze pro jeden výstup z LPT portu (konkrétně 8.)

Tento kód chci rozšířit pro všech 8 výstupů

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Nechce se mi ten humus luštit, ale čtení a zápis z/do portu se dá vyřešit pomocí jediného vlákna.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

V tom s Vámi naprosto souhlasím. Také že se zapisuje v jednom vláknu, ale co a kdy přesně se má zapsat se řeší v dalších 8.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ať už ten kód dělá cokoliv, je naprosto strašný.

1) Proč máte proměnné vlakno0 - vlakno7 a pak desítky řádků, které se liší jen použitou proměnnou? Co třeba dát vlákna do pole a pracovat s nimi nějak inteligentněji. To samé metody vl1 - vl7, zase - stačí přece ímít vlákna v poli a mít tam parametr.

2) Použít goto není vždy špatně, jen téměř vždy. V tomhle případě rozhodně goto nepoužívejte.

3) Používáte aktivní čekání (každou chvíli něco nastavujete nebo zjišťujete a mezi tím se uspáváte). Použijte pasivní čekání.

Na úlohy typu jedno vlákno generuje události a ostatní je zpracovávají (anebo víc vláken generuje a jedno zpracovává, to už je jedno), se typicky používá AutoResetEvent, která je k tomu určena a pokud to uděláte správně, nebude to zatěžovat procesor.

nahlásit spamnahlásit spam 2 / 2 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback