Wskazówki: wielowątkowość ze składnikiem BackgroundWorker (C# and Visual Basic)
W tym instruktażu przedstawiono sposób tworzenia wielowątkowych aplikacji, która przeszukuje plik tekstowy dla wystąpień wyrazu.Ilustruje to:
Definiowanie klasy przy użyciu metody, która może być wywoływana przez BackgroundWorker składnika.
Obsługa zdarzenia wywoływane przez BackgroundWorker składnika.
Uruchamianie BackgroundWorker uruchomienie metody składnika.
Wykonawczych Cancel przycisk, który zatrzymuje BackgroundWorker składnika.
Aby utworzyć interfejs użytkownika
Otwórz nowy Visual Basic lub aplikacji C# Windows projektu i utworzyć formularz o nazwie Form1.
Dodać dwa przyciski i cztery pola tekstowe do Form1.
Nazwy obiektów, jak pokazano w poniższej tabeli.
Obiekt
Właściwość
Ustawienie
Pierwszy przycisk
Name, Text
Rozpoczęcie-rozpoczęcie
Drugi przycisk
Name, Text
Anuluj, Anuluj
Pierwsze pole tekstowe
Name, Text
SourceFile, ""
Drugie pole tekstowe
Name, Text
CompareString, ""
Trzecie pole tekstowe
Name, Text
WordsCounted, "0"
Czwartego pola tekstowego
Name, Text
LinesCounted, "0"
Dodaj etykietę obok każdego pola tekstowego.Ustaw Text właściwości dla każdej etykiety, jak pokazano w poniższej tabeli.
Obiekt
Właściwość
Ustawienie
Pierwsza etykieta
Text
Plik źródłowy
Drugą etykietę
Text
Porównanie ciągu
Trzeci etykiety
Text
Pasujące wyrazy
Czwarty etykiety
Text
Liczone wiersze
Aby utworzyć składnik BackgroundWorker i subskrybować jego zdarzeń
Dodaj BackgroundWorker komponent z składników sekcji Przybornik do formularza.Pojawi się w zasobniku części formularza.
Ustaw następujące właściwości dla obiektu BackgroundWorker1 w Visual Basic lub obiektu backgroundWorker1 w języku C#.
Właściwość
Ustawienie
WorkerReportsProgress
Wartość true
WorkerSupportsCancellation
Wartość true
W języku C# tylko subskrybowanie zdarzeń obiektu backgroundWorker1.W górnej części Właściwości okna, kliknij zdarzenia ikona.Kliknij dwukrotnie RunWorkerCompleted zdarzenie, aby utworzyć metody obsługi zdarzenia.To samo ProgressChanged i DoWork zdarzenia.
Aby zdefiniować metodę, która zostanie uruchomione w osobnym wątku
Z Projekt menu, wybierz polecenie Add Class do dodawania klasy do projektu.Dodaj nowy element jest wyświetlane okno dialogowe.
Wybierz klasy z okna Szablony i typu Words.vb lub Words.cs w polu Nazwa.
Kliknij przycisk dodać.Words Klasy jest wyświetlany.
Dodaj następujący kod do Words klasy:
Public Class Words ' Object to store the current state, for passing to the caller. Public Class CurrentState Public LinesCounted As Integer Public WordsMatched As Integer End Class Public SourceFile As String Public CompareString As String Private WordCount As Integer = 0 Private LinesCounted As Integer = 0 Public Sub CountWords( ByVal worker As System.ComponentModel.BackgroundWorker, ByVal e As System.ComponentModel.DoWorkEventArgs ) ' Initialize the variables. Dim state As New CurrentState Dim line = "" Dim elapsedTime = 20 Dim lastReportDateTime = Now If CompareString Is Nothing OrElse CompareString = System.String.Empty Then Throw New Exception("CompareString not specified.") End If Using myStream As New System.IO.StreamReader(SourceFile) ' Process lines while there are lines remaining in the file. Do While Not myStream.EndOfStream If worker.CancellationPending Then e.Cancel = True Exit Do Else line = myStream.ReadLine WordCount += CountInString(line, CompareString) LinesCounted += 1 ' Raise an event so the form can monitor progress. If Now > lastReportDateTime.AddMilliseconds(elapsedTime) Then state.LinesCounted = LinesCounted state.WordsMatched = WordCount worker.ReportProgress(0, state) lastReportDateTime = Now End If ' Uncomment for testing. 'System.Threading.Thread.Sleep(5) End If Loop ' Report the final count values. state.LinesCounted = LinesCounted state.WordsMatched = WordCount worker.ReportProgress(0, state) End Using End Sub Private Function CountInString( ByVal SourceString As String, ByVal CompareString As String ) As Integer ' This function counts the number of times ' a word is found in a line. If SourceString Is Nothing Then Return 0 End If Dim EscapedCompareString = System.Text.RegularExpressions.Regex.Escape(CompareString) ' To count all occurrences of the string, even within words, remove ' both instances of "\b". Dim regex As New System.Text.RegularExpressions.Regex( "\b" + EscapedCompareString + "\b", System.Text.RegularExpressions.RegexOptions.IgnoreCase) Dim matches As System.Text.RegularExpressions.MatchCollection matches = regex.Matches(SourceString) Return matches.Count End Function End Class
public class Words { // Object to store the current state, for passing to the caller. public class CurrentState { public int LinesCounted; public int WordsMatched; } public string SourceFile; public string CompareString; private int WordCount; private int LinesCounted; public void CountWords( System.ComponentModel.BackgroundWorker worker, System.ComponentModel.DoWorkEventArgs e) { // Initialize the variables. CurrentState state = new CurrentState(); string line = ""; int elapsedTime = 20; DateTime lastReportDateTime = DateTime.Now; if (CompareString == null || CompareString == System.String.Empty) { throw new Exception("CompareString not specified."); } // Open a new stream. using (System.IO.StreamReader myStream = new System.IO.StreamReader(SourceFile)) { // Process lines while there are lines remaining in the file. while (!myStream.EndOfStream) { if (worker.CancellationPending) { e.Cancel = true; break; } else { line = myStream.ReadLine(); WordCount += CountInString(line, CompareString); LinesCounted += 1; // Raise an event so the form can monitor progress. int compare = DateTime.Compare( DateTime.Now, lastReportDateTime.AddMilliseconds(elapsedTime)); if (compare > 0) { state.LinesCounted = LinesCounted; state.WordsMatched = WordCount; worker.ReportProgress(0, state); lastReportDateTime = DateTime.Now; } } // Uncomment for testing. //System.Threading.Thread.Sleep(5); } // Report the final count values. state.LinesCounted = LinesCounted; state.WordsMatched = WordCount; worker.ReportProgress(0, state); } } private int CountInString( string SourceString, string CompareString) { // This function counts the number of times // a word is found in a line. if (SourceString == null) { return 0; } string EscapedCompareString = System.Text.RegularExpressions.Regex.Escape(CompareString); System.Text.RegularExpressions.Regex regex; regex = new System.Text.RegularExpressions.Regex( // To count all occurrences of the string, even within words, remove // both instances of @"\b" from the following line. @"\b" + EscapedCompareString + @"\b", System.Text.RegularExpressions.RegexOptions.IgnoreCase); System.Text.RegularExpressions.MatchCollection matches; matches = regex.Matches(SourceString); return matches.Count; } }
Do obsługi zdarzeń z wątku
Dodaj następujące programy obsługi zdarzeń w głównym formularzu:
Private Sub BackgroundWorker1_RunWorkerCompleted( ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs ) Handles BackgroundWorker1.RunWorkerCompleted ' This event handler is called when the background thread finishes. ' This method runs on the main thread. If e.Error IsNot Nothing Then MessageBox.Show("Error: " & e.Error.Message) ElseIf e.Cancelled Then MessageBox.Show("Word counting canceled.") Else MessageBox.Show("Finished counting words.") End If End Sub Private Sub BackgroundWorker1_ProgressChanged( ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs ) Handles BackgroundWorker1.ProgressChanged ' This method runs on the main thread. Dim state As Words.CurrentState = CType(e.UserState, Words.CurrentState) Me.LinesCounted.Text = state.LinesCounted.ToString Me.WordsCounted.Text = state.WordsMatched.ToString End Sub
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { // This event handler is called when the background thread finishes. // This method runs on the main thread. if (e.Error != null) MessageBox.Show("Error: " + e.Error.Message); else if (e.Cancelled) MessageBox.Show("Word counting canceled."); else MessageBox.Show("Finished counting words."); } private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { // This method runs on the main thread. Words.CurrentState state = (Words.CurrentState)e.UserState; this.LinesCounted.Text = state.LinesCounted.ToString(); this.WordsCounted.Text = state.WordsMatched.ToString(); }
Aby uruchomić i wywołać nowy wątek, który uruchamia metodę WordCount
Do programu, należy dodać następujące procedury:
Private Sub BackgroundWorker1_DoWork( ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs ) Handles BackgroundWorker1.DoWork ' This event handler is where the actual work is done. ' This method runs on the background thread. ' Get the BackgroundWorker object that raised this event. Dim worker As System.ComponentModel.BackgroundWorker worker = CType(sender, System.ComponentModel.BackgroundWorker) ' Get the Words object and call the main method. Dim WC As Words = CType(e.Argument, Words) WC.CountWords(worker, e) End Sub Sub StartThread() ' This method runs on the main thread. Me.WordsCounted.Text = "0" ' Initialize the object that the background worker calls. Dim WC As New Words WC.CompareString = Me.CompareString.Text WC.SourceFile = Me.SourceFile.Text ' Start the asynchronous operation. BackgroundWorker1.RunWorkerAsync(WC) End Sub
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { // This event handler is where the actual work is done. // This method runs on the background thread. // Get the BackgroundWorker object that raised this event. System.ComponentModel.BackgroundWorker worker; worker = (System.ComponentModel.BackgroundWorker)sender; // Get the Words object and call the main method. Words WC = (Words)e.Argument; WC.CountWords(worker, e); } private void StartThread() { // This method runs on the main thread. this.WordsCounted.Text = "0"; // Initialize the object that the background worker calls. Words WC = new Words(); WC.CompareString = this.CompareString.Text; WC.SourceFile = this.SourceFile.Text; // Start the asynchronous operation. backgroundWorker1.RunWorkerAsync(WC); }
Wywołanie StartThread metody z Start przycisku w formularzu:
Private Sub Start_Click() Handles Start.Click StartThread() End Sub
private void Start_Click(object sender, EventArgs e) { StartThread(); }
Aby zaimplementować przycisk Anuluj, który zatrzymuje wątek
Wywołanie StopThread procedurę z Click obsługi zdarzenia Cancel przycisku.
Private Sub Cancel_Click() Handles Cancel.Click ' Cancel the asynchronous operation. Me.BackgroundWorker1.CancelAsync() End Sub
private void Cancel_Click(object sender, EventArgs e) { // Cancel the asynchronous operation. this.backgroundWorker1.CancelAsync(); }
Testowanie
Teraz można przetestować aplikację, aby upewnić się, że działa on poprawnie.
Aby przetestować aplikację
Naciśnij klawisz F5, aby uruchomić aplikację.
Gdy formularz jest wyświetlany, podaj ścieżkę do pliku dla pliku, którą chcesz testować w sourceFile pole.Na przykład zakładając, że test pliku o nazwie Test.txt, wpisz C:\Test.txt.
W drugim polu tekstowym wpisz wyraz lub frazę do aplikacji wyszukać w pliku tekstowym.
Kliknij przycisk Start przycisku.LinesCounted Przycisk powinno rozpocząć się natychmiast zwiększany.Aplikacja wyświetla komunikat "Gotowe liczenia", po jej zakończeniu.
Aby przetestować przycisku Anuluj
Naciśnij klawisz F5, aby uruchomić aplikację, a następnie wprowadź plik nazwę i wyszukaj wyraz zgodnie z opisem w poprzedniej procedurze.Upewnij się, że wybrany plik jest wystarczająco duży, aby upewnić się, że będzie miał czas, aby anulować procedurę przed zakończeniem.
Kliknij przycisk Start przycisk, aby uruchomić aplikację.
Kliknij przycisk Cancel przycisku.Wniosek należy zatrzymać liczenia natychmiast.
Następne kroki
Ta aplikacja zawiera niektóre prostej obsługi błędów.Wykrywa puste ciągi.Można ustawić ten program bardziej niezawodne przez obsługi innych błędów, takie jak przekracza maksymalną liczbę słów lub wierszy, które mogą być zliczane.
Zobacz też
Zadania
Wskazówki: tworzenie prostego składnika wielowątkowego za pomocą języka Visual Basic
Porady: subskrybowanie i anulowanie subskrypcji zdarzeń (Przewodnik programowania w języku C#)