Wskazówki: tworzenie prostego składnika wielowątkowego za pomocą języka Visual Basic

BackgroundWorker Składnika zastępuje i dodaje funkcje do System.Threading nazw; Jednakże System.Threading obszaru nazw jest zachowywana zarówno dla zgodności z poprzednimi wersjami i wykorzystania w przyszłości, jeśli wybierzesz.Aby uzyskać więcej informacji, zobacz BackgroundWorker — Informacje o składniku.

Można napisać aplikacje, które są zdolne do wykonywania wielu zadań jednocześnie.Ta możliwość o nazwie wielowątkowości, lub wolnych wątków, jest wygodnym sposobem projektowania składników, które procesor i wymagają danych wejściowych użytkownika.Wykorzystanie przykład składnika, który może spowodować, że wielowątkowość byłoby składnik, który oblicza informacje listy płac.Składnik może przetwarzać dane wprowadzone do bazy danych przez użytkownika na jeden wątek podczas obliczania listy płac procesor były wykonywane w innym.Uruchamiając te procesy osobne wątki, użytkownicy nie muszą czekać na komputerze do wykonania obliczeń przed wprowadzeniem dodatkowych danych.W tym instruktażu utworzy prosty składnik wielowątkowe, który wykonuje jednocześnie wiele złożonych obliczeń.

Tworzenie projektu

Aplikacja składa się z jednego formularza i składnika.Użytkownika będą wprowadzane wartości i sygnał rozpoczęcia obliczeń do składnika.Formularz będzie następnie otrzymywać wartości składnika i wyświetlić je w formantów etykiet.Składnik będzie wykonywać obliczenia procesor i sygnału formularza po zakończeniu.Zmienne publiczne utworzy w składniku do przechowywania wartości otrzymanych od interfejsu użytkownika.Będzie także implementować metody w składniku wykonywać obliczenia na podstawie wartości tych zmiennych.

[!UWAGA]

Gdy funkcja jest zazwyczaj wygodniej dla metody, która oblicza wartość, argumenty nie mogą być przekazywane między wątki ani mogą być zwracane wartości.Wiele sposobów proste do dostarczania wartości wątków oraz otrzymują od ich wartości.W tej demonstracji poprzez aktualizację zmiennych publicznych zwróci wartości do interfejsu użytkownika i zdarzenia będą używane do powiadamiania głównego programu po zakończeniu wykonywania wątku.

Okna dialogowe i polecenia menu może być różnią się od opisane w pomocy w zależności od ustawień aktywny lub edition.Aby zmienić ustawienia, wybierz polecenie Ustawienia eksportu i importu na Narzędzia menu.Aby uzyskać więcej informacji, zobacz Dostosowywanie ustawień środowiska deweloperskiego w Visual Studio.

Aby utworzyć formularz

  1. Utwórz nowy Aplikacji Windows projektu.

  2. Nazwa aplikacji Calculations i zmień nazwę Form1.vb jako frmCalculations.vb.

  3. Gdy pojawi się monit o Zmień nazwę Visual Studio Form1 kod elementu, kliknij przycisk Tak.

    Ten formularz będzie służyć jako podstawowy interfejs aplikacji.

  4. Dodać pięć Label kontroluje cztery Button formanty i jednego TextBox formantu do formularza.

    Formant

    Nazwa

    Tekst

    Label1

    lblFactorial1

    (puste)

    Label2

    lblFactorial2

    (puste)

    Label3

    lblAddTwo

    (puste)

    Label4

    lblRunLoops

    (puste)

    Label5

    lblTotalCalculations

    (puste)

    Button1

    btnFactorial1

    Silnia

    Button2

    btnFactorial2

    Silnia - 1

    Button3

    btnAddTwo

    Dodać dwie

    Button4

    btnRunLoops

    Uruchom pętli

    TextBox1

    txtValue

    (puste)

Aby utworzyć składnik kalkulatora

  1. Z projektu menu wybierz Dodać składnik.

  2. Nazwa tego składnika Calculator.

Aby dodać zmiennych publicznych do składnika kalkulatora

  1. Otwórz Edytor kodu dla Calculator.

  2. Dodać instrukcje do tworzenia zmiennych publicznych, które będą używane do przekazania wartości z frmCalculations do każdego wątku.

    Zmienna varTotalCalculations będzie Zachowaj sumy całkowitej liczby obliczenia wykonywane przez składnik i inne zmienne otrzymają wartości z formularza.

    Public varAddTwo As Integer
    Public varFact1 As Integer
    Public varFact2 As Integer
    Public varLoopValue As Integer
    Public varTotalCalculations As Double = 0
    

Aby dodać metod i zdarzeń do składnika kalkulatora

  1. Zadeklarować zdarzenia, które składnik będą używać do komunikowania się wartości do formularza.Bezpośrednio pod deklaracjami zmiennych w poprzednim kroku, wpisz następujący kod:

    Public Event FactorialComplete(ByVal Factorial As Double, ByVal _
       TotalCalculations As Double)
    Public Event FactorialMinusComplete(ByVal Factorial As Double, ByVal _
       TotalCalculations As Double)
    Public Event AddTwoComplete(ByVal Result As Integer, ByVal _
       TotalCalculations As Double)
    Public Event LoopComplete(ByVal TotalCalculations As Double, ByVal _
       Counter As Integer)
    
  2. Bezpośrednio pod deklaracjami zmiennych w kroku 1, wpisz następujący kod:

    ' This sub will calculate the value of a number minus 1 factorial 
    ' (varFact2-1!).
    Public Sub FactorialMinusOne()
       Dim varX As Integer = 1
       Dim varTotalAsOfNow As Double
       Dim varResult As Double = 1
       ' Performs a factorial calculation on varFact2 - 1.
       For varX = 1 to varFact2 - 1
          varResult *= varX
          ' Increments varTotalCalculations and keeps track of the current
          ' total as of this instant.
          varTotalCalculations += 1
          varTotalAsOfNow = varTotalCalculations
       Next varX
       ' Signals that the method has completed, and communicates the 
       ' result and a value of total calculations performed up to this 
       ' point
       RaiseEvent FactorialMinusComplete(varResult, varTotalAsOfNow)
    End Sub
    
    ' This sub will calculate the value of a number factorial (varFact1!).
    Public Sub Factorial()
       Dim varX As Integer = 1
       Dim varResult As Double = 1
       Dim varTotalAsOfNow As Double = 0
       For varX = 1 to varFact1
           varResult *= varX
           varTotalCalculations += 1
           varTotalAsOfNow = varTotalCalculations
       Next varX
       RaiseEvent FactorialComplete(varResult, varTotalAsOfNow)
    End Sub
    
    ' This sub will add two to a number (varAddTwo + 2).
    Public Sub AddTwo()
       Dim varResult As Integer
       Dim varTotalAsOfNow As Double
       varResult = varAddTwo + 2
       varTotalCalculations += 1
       varTotalAsOfNow = varTotalCalculations
       RaiseEvent AddTwoComplete(varResult, varTotalAsOfNow)
    End Sub
    
    ' This method will run a loop with a nested loop varLoopValue times.
    Public Sub RunALoop()
       Dim varX As Integer
       Dim varY As Integer
       Dim varTotalAsOfNow As Double
       For varX = 1 To varLoopValue
          ' This nested loop is added solely for the purpose of slowing
          ' down the program and creating a processor-intensive
          ' application.
          For varY = 1 To 500
             varTotalCalculations += 1
             varTotalAsOfNow = varTotalCalculations
          Next
       Next
       RaiseEvent LoopComplete(varTotalAsOfNow, varX - 1)
    End Sub
    

Transferowanie danych wejściowych użytkownika do składnika

Następnym krokiem jest dodanie kodu do frmCalculations do odbierania danych wejściowych od użytkownika oraz do transferu i otrzymują wartości do i z Calculator składnika.

Aby zaimplementować frontonu funkcji frmCalculations

  1. Wybierz Roztwór budować z budować menu.

  2. Otwórz frmCalculations Windows Forms projektanta.

  3. Zlokalizuj Składniki obliczenia kartę w Przybornik.Przeciągnij Kalkulator składnik na powierzchnię projektu.

  4. W Właściwości systemu windows, kliknij zdarzenia przycisku.

  5. Kliknij dwukrotnie każde z czterech zdarzeń do tworzenia zdarzeń w frmCalculations.Należy powrócić do projektanta po utworzeniu każdego programu obsługi zdarzeń.

  6. Wstaw następujący kod do obsługi zdarzenia formularza będzie otrzymywać od Calculator1:

    Private Sub Calculator1_AddTwoComplete(ByVal Result As System.Int32, ByVal TotalCalculations As System.Double) Handles Calculator1.AddTwoComplete
        lblAddTwo.Text = Result.ToString
        btnAddTwo.Enabled = True
        lblTotalCalculations.Text = "TotalCalculations are " & _
            TotalCalculations.ToString
    End Sub
    
    Private Sub Calculator1_FactorialComplete(ByVal Factorial As System.Double, ByVal TotalCalculations As System.Double) Handles Calculator1.FactorialComplete
        ' Displays the returned value in the appropriate label.
        lblFactorial1.Text = Factorial.ToString
        ' Re-enables the button so it can be used again.
        btnFactorial1.Enabled = True
        ' Updates the label that displays the total calculations performed
        lblTotalCalculations.Text = "TotalCalculations are " & _
           TotalCalculations.ToString
    End Sub
    
    Private Sub Calculator1_FactorialMinusComplete(ByVal Factorial As System.Double, ByVal TotalCalculations As System.Double) Handles Calculator1.FactorialMinusComplete
        lblFactorial2.Text = Factorial.ToString
        btnFactorial2.Enabled = True
        lblTotalCalculations.Text = "TotalCalculations are " & _
            TotalCalculations.ToString
    End Sub
    
    Private Sub Calculator1_LoopComplete(ByVal TotalCalculations As System.Double, ByVal Counter As System.Int32) Handles Calculator1.LoopComplete
        btnRunLoops.Enabled = True
        lblRunLoops.Text = Counter.ToString
        lblTotalCalculations.Text = "TotalCalculations are " & _
           TotalCalculations.ToString
    End Sub
    
  7. Zlokalizuj End Class instrukcji na dole Edytor kodu.Bezpośrednio nad nim, Dodaj następujący kod do obsługi kliknięcia przycisku:

    Private Sub btnFactorial1_Click(ByVal sender As Object, ByVal e As _
       System.EventArgs) Handles btnFactorial1.Click
       ' Passes the value typed in the txtValue to Calculator.varFact1.
       Calculator1.varFact1 = CInt(txtValue.Text)
       ' Disables the btnFactorial1 until this calculation is complete.
       btnFactorial1.Enabled = False
       Calculator1.Factorial()
    End Sub
    
    Private Sub btnFactorial2_Click(ByVal sender As Object, ByVal e _
       As System.EventArgs) Handles btnFactorial2.Click
       Calculator1.varFact2 = CInt(txtValue.Text)
       btnFactorial2.Enabled = False
       Calculator1.FactorialMinusOne()
    End Sub
    
    Private Sub btnAddTwo_Click(ByVal sender As Object, ByVal e As _
       System.EventArgs) Handles btnAddTwo.Click
       Calculator1.varAddTwo = CInt(txtValue.Text)
       btnAddTwo.Enabled = False
       Calculator1.AddTwo()
    End Sub
    
    Private Sub btnRunLoops_Click(ByVal sender As Object, ByVal e As _
       System.EventArgs) Handles btnRunLoops.Click
       Calculator1.varLoopValue = CInt(txtValue.Text)
       btnRunLoops.Enabled = False
       ' Lets the user know that a loop is running.
       lblRunLoops.Text = "Looping"
       Calculator1.RunALoop()
    End Sub
    

Testowanie aplikacji

Tworzony projekt formularza i składnik zdolny do kilku złożonych obliczeń.Chociaż nie wprowadziły wielowątkowości możliwości jeszcze, będzie badanie projektu sprawdzić jego funkcjonalności, przed kontynuowaniem.

Aby przetestować projekt

  1. Z debugowania menu wybierz Uruchomić debugowanie.Aplikacja zaczyna i frmCalculations pojawi się.

  2. W polu tekstowym wpisz 4, następnie kliknij przycisk o nazwie Dodać dwa.

    Cyfrę "6" powinien być wyświetlany w etykiecie poniżej i "1 są obliczenia całkowitej" powinien być wyświetlany w lblTotalCalculations.

  3. Teraz kliknij przycisk o nazwie silnia - 1.

    Cyfrę "6" powinien być wyświetlany poniżej przycisku i lblTotalCalculations teraz odczytuje "Są obliczenia całkowitej 4."

  4. Zmień wartość w polu tekstowym, aby 20, następnie kliknij przycisk o nazwie silnia.

    Poniżej, jest wyświetlany numer "2.43290200817664E + 18" i lblTotalCalculations teraz odczytuje "Sumy są 24."

  5. Zmień wartość w polu tekstowym 50000, a następnie kliknij przycisk oznaczony Uruchomić pętli a.

    Uwaga jest niewielki, ale zauważalne interwał przed tego przycisku zostanie ponownie włączony.Etykieta przycisku tego należy przeczytać "50000" i obliczania sum, wyświetlane są "25000024".

  6. Zmień wartość w polu tekstowym, aby 5000000 i kliknij przycisk z etykietą Uruchomić pętli ai natychmiast kliknij przycisk z etykietą Dodać dwa.Kliknij Dodać dwa ponownie.

    Przycisk nie odpowie, ani formantu w formularzu odpowie zakończenia pętli.

    Uruchomienie programu jednym wątku wykonywania obliczeń procesor, jak w powyższym przykładzie mają tendencję do blokuje program, do momentu zakończenia obliczeń.W następnej sekcji zostaną dodane wielowątkowości zdolności do aplikacji tak, aby wiele wątków może uruchomić jednocześnie.

Dodanie możliwości wielowątkowość

Poprzedni przykład wykazać ograniczenia aplikacje uruchamiane w jednym wątku wykonywania.W następnej sekcji będzie używać Thread klasy, aby dodać wiele wątków wykonanie do składnika.

Aby dodać podprocedury wątków

  1. Otwórz Calculator.vb w Edytor kodu.W górnej części kodu zlokalizować Public Class Calculator linii.Bezpośrednio pod nim, należy wpisać:

    ' Declares the variables you will use to hold your thread objects.
    Public FactorialThread As System.Threading.Thread
    Public FactorialMinusOneThread As System.Threading.Thread
    Public AddTwoThread As System.Threading.Thread
    Public LoopThread As System.Threading.Thread
    
  2. Bezpośrednio przed End Class instrukcji w dolnej części kodu, dodaj następującą metodę:

    Public Sub ChooseThreads(ByVal threadNumber As Integer)
    ' Determines which thread to start based on the value it receives.
       Select Case threadNumber
          Case 1
             ' Sets the thread using the AddressOf the subroutine where
             ' the thread will start.
             FactorialThread = New System.Threading.Thread(AddressOf _
                Factorial)
             ' Starts the thread.
             FactorialThread.Start()
          Case 2
             FactorialMinusOneThread = New _
                System.Threading.Thread(AddressOf FactorialMinusOne)
             FactorialMinusOneThread.Start()
          Case 3
             AddTwoThread = New System.Threading.Thread(AddressOf AddTwo)
             AddTwoThread.Start()
          Case 4
             LoopThread = New System.Threading.Thread(AddressOf RunALoop)
             LoopThread.Start()
       End Select
    End Sub
    

    Gdy Thread tworzyć wystąpień obiektu, wymaga argumentu w postaci ThreadStart obiektu.ThreadStart Obiekt jest pełnomocnika, który wskazuje adres podprocedurę, gdzie ma rozpocząć wątku.A ThreadStart obiekt nie może mieć parametrów lub przebiegu, wartości i nie może zatem wskazują funkcję.AddressOf — Operator (Visual Basic) Zwraca pełnomocnika, który służy jako ThreadStart obiektu.ChooseThreads Sub właśnie zaimplementowanej otrzymają wartości z programu to wywołanie i wartości można używać do określenia odpowiedniego wątku, aby uruchomić.

Aby dodać kod uruchomienie wątku frmCalculations

  1. Otwórz frmCalculations.vb pliku w Edytor kodu.Locate Sub btnFactorial1_Click.

    1. Komentarz linii, który wywołuje Calculator1.Factorialmetoda bezpośrednio, jak pokazano:

      ' Calculator1.Factorial
      
    2. Dodaj następujący wiersz do wywołania Calculator1.ChooseThreads metody:

      ' Passes the value 1 to Calculator1, thus directing it to start the ' correct thread.
      Calculator1.ChooseThreads(1)
      
  2. Wprowadzić zmiany podobne do drugiej button_click podprocedury.

    [!UWAGA]

    Należy uwzględnić odpowiednią wartość dla threads argumentu.

    Po zakończeniu, kod powinno wyglądać podobnie do następującego:

    Private Sub btnFactorial1_Click(ByVal sender As Object, ByVal e As _
       System.EventArgs) Handles btnFactorial1.Click
       ' Passes the value typed in the txtValue to Calculator.varFact1.
       Calculator1.varFact1 = CInt(txtValue.Text)
       ' Disables the btnFactorial1 until this calculation is complete.
       btnFactorial1.Enabled = False
       ' Calculator1.Factorial()
       ' Passes the value 1 to Calculator1, thus directing it to start the
       ' Correct thread.
       Calculator1.ChooseThreads(1)
    End Sub
    
    Private Sub btnFactorial2_Click(ByVal sender As Object, ByVal e As _
       System.EventArgs) Handles btnFactorial2.Click
       Calculator1.varFact2 = CInt(txtValue.Text)
       btnFactorial2.Enabled = False
       ' Calculator1.FactorialMinusOne()
       Calculator1.ChooseThreads(2)
    End Sub
    
    Private Sub btnAddTwo_Click(ByVal sender As Object, ByVal e As _
       System.EventArgs) Handles btnAddTwo.Click
       Calculator1.varAddTwo = CInt(txtValue.Text)
       btnAddTwo.Enabled = False
       ' Calculator1.AddTwo()
       Calculator1.ChooseThreads(3)
    End Sub
    
    Private Sub btnRunLoops_Click(ByVal sender As Object, ByVal e As _
       System.EventArgs) Handles btnRunLoops.Click
       Calculator1.varLoopValue = CInt(txtValue.Text)
       btnRunLoops.Enabled = False
       ' Lets the user know that a loop is running.
       lblRunLoops.Text = "Looping"
       ' Calculator1.RunALoop()
       Calculator1.ChooseThreads(4)
    End Sub
    

Kierowanie połączeń do formantów

Teraz ułatwi aktualizacją wyświetlania w formularzu.Ponieważ formanty są zawsze własnością głównego wątku wykonywania, każde wywołanie formantu z wątku podrzędnego wymaga kierowanie wywołania.Kierowanie jest aktem przenoszenia wywołania przez granice wątków i jest bardzo kosztowne w odniesieniu do zasobów.Aby zminimalizować ilość kierowanie musi wystąpić i w sposób bezpieczny wątek obsługi wywołania upewnij się, będą używać BeginInvoke do wywołania metody w głównym wątku wykonanie, zminimalizować ilość wątku transgraniczny, kierowanie musi wystąpić.Konieczne jest wywołanie tego rodzaju podczas wywoływania metody manipulujące formantów.Aby uzyskać więcej informacji, zobacz Porady: manipulowanie kontrolkami pochodzącymi z wątków.

Aby utworzyć wywoływanie kontroli procedury

  1. Otwórz Edytor kodu dla frmCalculations.W sekcji deklaracji Dodaj następujący kod.

    Public Delegate Sub FHandler(ByVal Value As Double, ByVal _
       Calculations As Double)
    Public Delegate Sub A2Handler(ByVal Value As Integer, ByVal _
       Calculations As Double)
    Public Delegate Sub LDhandler(ByVal Calculations As Double, ByVal _
       Count As Integer)
    

    Invokei BeginInvoke wymagają pełnomocnika do odpowiedniej metody jako argumentu.Te wiersze zadeklarować pełnomocnika podpisy, które będą używane przez BeginInvoke do wywołania właściwych metod.

  2. Dodaj następujące metody pusty do kodu.

    Public Sub FactHandler(ByVal Factorial As Double, ByVal TotalCalculations As _
       Double)
    End Sub
    Public Sub Fact1Handler(ByVal Factorial As Double, ByVal TotalCalculations As _
       Double)
    End Sub
    Public Sub Add2Handler(ByVal Result As Integer, ByVal TotalCalculations As _
       Double)
    End Sub
    Public Sub LDoneHandler(ByVal TotalCalculations As Double, ByVal Counter As _
       Integer)
    End Sub
    
  3. Z Edytuj menu Użyj Wytnij i Wklej do wycinania kod z Sub Calculator1_FactorialComplete i wklej go do FactHandler.

  4. Repeat the previous step for Calculator1_FactorialMinusComplete and Fact1Handler, Calculator1_AddTwoComplete and Add2Handler, and Calculator1_LoopComplete and LDoneHandler.

    Po zakończeniu powinny być żadnego kodu pozostające w Calculator1_FactorialComplete, Calculator1_FactorialMinusComplete, Calculator1_AddTwoComplete, i Calculator1_LoopCompletei wszystkie te powinien zawierać powinno zostały przeniesione do odpowiednich nowych metod kodu.

  5. Wywołanie BeginInvoke metody do wywołania metody asynchronicznie.Można wywołać BeginInvoke z jednego formularza (me) lub formantów formularza:

    Private Sub Calculator1_FactorialComplete(ByVal Factorial As System.Double, ByVal TotalCalculations As System.Double) Handles Calculator1.FactorialComplete
       ' BeginInvoke causes asynchronous execution to begin at the address
       ' specified by the delegate. Simply put, it transfers execution of 
       ' this method back to the main thread. Any parameters required by 
       ' the method contained at the delegate are wrapped in an object and 
       ' passed. 
       Me.BeginInvoke(New FHandler(AddressOf FactHandler), New Object() _
          {Factorial, TotalCalculations })
    End Sub
    
    Private Sub Calculator1_FactorialMinusComplete(ByVal Factorial As System.Double, ByVal TotalCalculations As System.Double) Handles Calculator1.FactorialMinusComplete
       Me.BeginInvoke(New FHandler(AddressOf Fact1Handler), New Object() _
          { Factorial, TotalCalculations })
    End Sub
    
    Private Sub Calculator1_AddTwoComplete(ByVal Result As System.Int32, ByVal TotalCalculations As System.Double) Handles Calculator1.AddTwoComplete
       Me.BeginInvoke(New A2Handler(AddressOf Add2Handler), New Object() _
          { Result, TotalCalculations })
    End Sub
    
    Private Sub Calculator1_LoopComplete(ByVal TotalCalculations As System.Double, ByVal Counter As System.Int32) Handles Calculator1.LoopComplete
       Me.BeginInvoke(New LDHandler(AddressOf Ldonehandler), New Object() _
          { TotalCalculations, Counter })
    End Sub
    

    Może ona wydawać, że obsługi zdarzeń jest po prostu nawiązywania połączenia do następnej metody.Metoda powoływać się w głównym wątku operacji faktycznie powoduje obsługi zdarzeń.Podejście to zapisuje na wywołania przez granice wątków i pozwala skutecznie i bez obawy powoduje blokowanie aplikacji wielowątkowych.Szczegółowe informacje dotyczące pracy z formantów w środowisku wielowątkowym Porady: manipulowanie kontrolkami pochodzącymi z wątków.

  6. Zapisz swoją pracę.

  7. Sprawdź swoje rozwiązanie, wybierając Uruchomić debugowanie z debugowania menu.

    1. Typ 10000000 w polu tekstowym i kliknij Uruchomić pętli a.

      "Pętli" jest wyświetlany w etykiecie poniżej tego przycisku.Ta pętla powinny podjąć znaczną ilość czasu na uruchomienie.Wykona on zbyt wcześnie, należy odpowiednio dostosować rozmiar liczby.

    2. W krótkim odstępie czasu kliknij wszystkie trzy przyciski, które są nadal włączone.Znajdziesz, że wszystkie przyciski odpowiadać na dane wejściowe.Etykieta pod Dodać dwa powinny być najpierw do wyświetlenia wyniku.Wyniki wyświetlane są później w etykietach poniżej przycisków silni.Te wyniki oceny do nieskończoności, jako liczba zwracanych przez 10 000 000 silnia jest zbyt duży dla zmiennej podwójnej precyzji zawierają.Wreszcie, opóźnieniem dodatkowe wyniki są zwracane pod Uruchomić pętli a przycisku.

      Po prostu obserwowane, czterech oddzielnych zestawów obliczenia były wykonywane jednocześnie na czterech oddzielnych wątków.Interfejs użytkownika pozostała odpowiadać wejściowe i wyniki zostały zwrócone po każdego wątku zakończone.

Koordynowanie wątkom

Doświadczonych użytkowników, aplikacji wielowątkowych mogą postrzegać subtelnych usterka kod wpisanych.Odwołaj wiersze kodu pochodzące z każdego programowego wykonywania obliczeń w Calculator:

varTotalCalculations += 1
varTotalAsOfNow = varTotalCalculations

Te dwa wiersze kodu, zwiększ wartość zmiennej publicznej varTotalCalculations i zmienna lokalna varTotalAsOfNow tej wartości.Ta wartość jest zwracany do frmCalculations i wyświetlane w formancie etykiety.Ale jest zwracany poprawny?Jeśli tylko pojedynczego wątku wykonywania jest uruchomiony, odpowiedź jest wyraźnie tak.Ale jeśli korzystasz z wielu wątków, odpowiedź staje się bardziej niepewna.Każdy wątek ma możliwość Zwiększ wartość zmiennej varTotalCalculations.Możliwe, że po jednym wątku zwiększa tej zmiennej, ale przed kopiuje wartość varTotalAsOfNow, inny wątek może zmienić wartość tej zmiennej, zwiększając ją.Prowadzi to możliwość, że każdy wątek w rzeczywistości raportowania niedokładnych wyników.Visual Basic zapewnia SyncLock — Instrukcja , aby umożliwić synchronizacji wątków, aby zapewnić, że każdy wątek ma zawsze zwraca dokładny wynik.Składnia SyncLock jest następujący:

SyncLock AnObject
   Insert code that affects the object
   Insert some more
   Insert even more
' Release the lock
End SyncLock

Gdy SyncLock jest wprowadzana w bloku, wykonanie na określone wyrażenie jest zablokowana, dopóki określony wątek ma wyłączną blokadę na dany obiekt.W powyższym przykładzie wykonywanie jest zablokowany na AnObject.SyncLockmusi być używana z obiektu, który zwraca odwołanie niż wartość.Następnie kontynuować wykonywanie jako blok bez zakłóceń z innych wątków.Zestaw instrukcji, które wykonywane jako jednostka są określane jako atomic.Gdy End SyncLock jest napotkał, wyrażenie jest zwalniany i wątki mogą kontynuować normalnie.

Aby dodać instrukcję SyncLock do aplikacji

  1. Otwórz Calculator.vb w Edytor kodu.

  2. Zlokalizuj każde wystąpienie następujący kod:

    varTotalCalculations += 1
    varTotalAsOfNow = varTotalCalculations
    

    Powinny być cztery wystąpienia tego kodu, jeden w każdej metodzie obliczeń.

  3. Zmodyfikować ten kod, tak aby otrzymuje brzmienie:

    SyncLock Me
       varTotalCalculations += 1
       varTotalAsOfNow = varTotalCalculations
    End SyncLock
    
  4. Zapisz swoją pracę i przetestować w poprzednim przykładzie.

    Można zauważyć niewielki wpływ na wydajność programu.Jest to spowodowane uzyskiwane są wyłączną blokadę na składnik przerywa wykonywanie wątków.Chociaż zapewnia dokładność, podejście to utrudnia niektóre korzyści wydajności wiele wątków.Należy uważnie rozważyć potrzebę blokowania wątków i je tylko wtedy, gdy jest to absolutnie konieczne.

Zobacz też

Zadania

Porady: koordynowanie wielu wątków wykonania

Wskazówki: tworzenie prostego składnika wielowątkowego za pomocą języka C#

Informacje

BackgroundWorker

Koncepcje

Asynchroniczny wzorzec oparty na zdarzeniach — przegląd

Inne zasoby

Programowanie przy użyciu składników

Programowanie składników — wskazówki

Wielowątkowość w składnikach