Uruchamianie drugiego wątku z opóźnieniem

0

Siema. Mam taki thread:

rozpoczęcie:

              luba = 0
                Dim thread As System.Threading.Thread
                thread = New System.Threading.Thread(AddressOf pls)
                thread.IsBackground = True
                thread.Start()

pls:

    Private Sub pls()
Dim zua as integer
For zua = luba TO 10
...
Next

    End Sub

Teraz potrzebuje podwójnie uruchomić wątek pls, czyli start zua = 0 i po chwili startuje od razu drugi, czyli 2 pracują ze startem opóźnionym ale równocześnie. Da się coś takiego zrobić?

Próbowałem na wiele sposobów, zmieniałem luba na 1, ale za każdym razem całe for wykonywało się w razy.

jak to naprawić?

0

ustaw timera na odpowiedni czas i w timerze twórz drugi wątek.

0

Azarien, nie bardzo.

Wtedy wykonuje się 2 razy
więc:

0
0
1
1
2
2
3
3
itd.

A mi chodzi o to, by przyspieszyć wykonywanie tego for, aby było normalnie

0
1
2
3
itd.

Da się coś takiego zrobić?

0

Co dokładnie chcesz osiągnąć poprzez uruchomienie drugiego wątku?
Chcesz żeby część pracy wykonał pierwszy, a część drugi, czy żeby oba robiły to samo, ale z opóźnieniem?
Eg1:
0 - wątek 1
1 - wątek 1
2 - wątek 2
3 - wątek 1
4 - wątek 2
, czy
Eg2
0 - wątek 1
1 - wątek 1
2 - wątek 1
0 - wątek 2
3 - wątek 1
1 - wątek 2
4 - wątek 1
2 - wątek 2

0

Chcę, aby drugi wątek pomógł 1 i przyspieszył działanie pętli for.

0

To nie działa tak jak myślisz.

Jedyne co ci może pomóc w takiej sytuacji to jest Parallel LINQ (PLINQ)

http://msdn.microsoft.com/en-us/library/dd460688.aspx

(jeśli używasz .NET 4.0). Nie wiem co prawda jak to się ma do VB, ale chyba jest specyfikacja.

0

Przede wszystkim nikt nie możne zagwarantować, że stworzenie nowych wątków przyspieszy pracę(w tym wypadku na pewno nie) - niektórych problemów nie da się "zrównoleglić"(np. gdy wynik kolejnej iteracji jest ściśle zależny od poprzedniej). Nikt nie może zagwarantować, że wątek 2(i następne) w ogóle zdąży coś zrobić, ani że zachowana będzie kolejność(w konsoli możesz dostać np. 1, 2, 3, 5, 6, 4, 7, chyba że zaprojektujesz aplikację tak, aby kolejność była zachowana, ale to zazwyczaj bez sensu).
Żeby 2 wątki się wzajemnie wspomagały, muszą robić to samo, na tych samych danych, więc zmienna zua musi być współdzielona. Gdy więcej niż 1 wątek ma dostęp do jakiejś danej(i nie jest ona tylko do odczytu), konieczna jest synchronizacja. Istnieją różne metody synchronizacji, w zależności od problemu jaki jest do rozwiązania.

Nie bijcie, nie używałem VB już dawno ;P

Module Module1

    'do synchronizacji, wszystkie zmienne jako pola klasy, a nie zmienne wewnątrz funkcji/metody(no może poza delay)
    Dim obj As New Object
    Dim delay As Integer
    Dim luba As Integer
    Dim zua As Integer
    Dim die As Boolean
    Dim delay2 As Integer
    Dim rand As New Random
    
    Sub Main()
        luba = 0
        zua = 0
        delay = 500
        die = False

        Dim thread As System.Threading.Thread
        thread = New System.Threading.Thread(AddressOf pls2)
        thread.IsBackground = True
        thread.Name = "Thread 1"
        Dim thread2 As System.Threading.Thread
        thread2 = New System.Threading.Thread(AddressOf pls2)
        thread2.IsBackground = True
        thread2.Name = "Thread 2"

        zua = luba
        thread.Start()
        System.Threading.Thread.Sleep(delay)
        thread2.Start()

        Console.ReadLine()
    End Sub

    Private Sub pls()
        While Not die
            SyncLock (obj)
                'Używaj liczby większych niż 10, bo to się wykona zanim drugi wątek w ogóle powstanie
                If zua > 10000 Then
                    die = True
                Else
                    Console.WriteLine("{0} {1}", zua.ToString, Threading.Thread.CurrentThread.Name)
                    zua += 1
                End If
            End SyncLock
        End While
    End Sub

    Private Sub pls2()
        Dim localTmp As Integer
        While Not die
            SyncLock (obj)
                'Używaj liczby większych niż 10, bo to się wykona zanim drugi wątek w ogóle powstanie
                If zua > 10000 Then
                    die = True
                Else
                    localTmp = zua
                    zua += 1
                End If
            End SyncLock
            If Not die Then
                Console.WriteLine("{0} {1}", localTmp .ToString, Threading.Thread.CurrentThread.Name)
            End If
        End While
    End Sub

End Module

U mnie pls dawało zazwyczaj kilka razy pod rząd Thread 1, potem kilka razy Thread 2(a propos podziału pracy), natomiast jeśli wątki wywołasz z pls2 to zobaczysz, o co mi z kolejnością chodziło.

0

j_s_r_n, zrobiłem to nieco inaczej, jednak jest jeden błąd ze startem.

Stat nowych threadów:

                For ii As Integer = 0 To 1
                    ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf webs))
                Next

webs:

   Private Sub webs()

ss1  = 100
        If ListBox1.Items.Count <> 0 Then
            ' for
            For zacz As Integer = 0 To ss1
  Try
                        ziarno1 = ListBox1.Items(0)
                        ListBox1.Items.RemoveAt(0)
                        Me.Invoke(New EventHandler(AddressOf work))

                    Catch ex As Exception

                        skk1 = ziarno1
                        Me.Invoke(New EventHandler(AddressOf warning))

                    End Try


                    liczuba = liczuba + 1
                   add = count(ziarno1.ToString)

                    If add <> "" Then

                        Me.Invoke(New EventHandler(AddressOf work))
                    .......
                  End if
            Next

End if


End sub

ListBox1.Items:

0
1
2
3
4
...

Ale pętla for w sub webs:

2
3
4
5
6
7
..

Czyli początku nie wykonuje, dlaczego?

0
  1. Za mało danych. Nie widać co jest globalne(współdzielone), ani co się dzieje.
  2. Nie ma synchronizacji - to, wbrew pozorom, może być powodem gigantycznej ilości problemów, szczególnie w połączeniu z Windows forms.
  3. Co to jest?

Ale pętla for w sub webs:

liczuba?

0

j_s_r_n,
ThreadPool.QueueUserWorkItem to start 2 na raz threadów. One mają przyspieszyć działanie pętli * For zacz As Integer = 0 To ss1 * więc zastosowałem listbox.

ziarno1 = ListBox1.Items(0)

Listbox1 zawiera nr tablicy, po kolei gdzie są zawarte niezbędne dane do wykonania dalszej pętli, czyli nr tablicy, gdzie znajduje się adres strony www.
Dalsza część for jest mało ważna, więc nie wpisuje jej tutaj. Wszystko działa pięknie ładnie, ale ten początek najgorzej. Jeśli ma wykonywać 2 wątki na raz, to startuje 2,3,4,5 jeśli ma być jeden wątek, to normalnie: 0,1,2,3,4..., w przypadku 4: 4,5,6,7 - reasumując, brakuje tu początku od 0 aż do liczby threadów - 1, ale dlaczego?

0

Być może to kwestia braku synchronizacji, żeby to sprawdzić dodaj :

Dim obj As New Object

Private Sub webs()
SyncLock (obj)
'(reszta kodu)
End SyncLock
End Sub

Program będzie działał jak sekwencyjny(1 wątkowy), albo i wolniej, ale zobaczymy, czy to właśnie to nie jest problemem.
Dalej nie wiem, co to te: 0, 1, 2, 3, 4. Czy masz to wypisywane do konsoli/textboxa, czy ustawiasz breakpointa i podglądasz wartość zmiennej(nie rób tak, pÓÓÓÓki nie nauczysz się lepiej synchronizacji i nie będziesz absolutnie pewny, że ona dobrze działa). Debug aplikacji wielowątkowych to naprawdę trudna rzecz, szczególnie dla kogoś początkującego. Jeżeli robisz to np. przez breakpointa, to tak naprawdę zatrzymujesz wykonanie kodu w danym punkcie dla każdego z wątków. To znaczy, że do tego punktu każdy z nich się wykona. To znaczy, że gdybyś umieścił go np. tu:

    liczuba = liczuba + 1
*  add = count(ziarno1.ToString)

to liczuba zostanie zwiększona o 1 tyle razy, ile wątków uruchomiłeś, zanim zdążysz podejrzeć wartość zmiennej.

0

j_s_r_n, jednak to nie to, wiesz jak użyć PLINQ?

0

Tylko tyle, ile mi Google podpowie

1 użytkowników online, w tym zalogowanych: 0, gości: 1