Sdílet prostřednictvím


Návod: Multithreading s komponentou BackgroundWorker (C# a Visual Basic)

Názorný postup vytvoření aplikace s více podprocesy, která vyhledá výskyty slova do textového souboru.Ukazuje:

Vytvořit uživatelské rozhraní

  1. Otevřete nový Visual Basic nebo C# Windows aplikace project a vytvořte formulář s názvem Form1.

  2. Přidat dvě tlačítka a čtyři textová pole Form1.

  3. Název objekty uvedené v následující tabulce.

    Objekt

    Property

    Nastavení

    První tlačítko

    Name, Text

    Start Start

    Druhé tlačítko

    Name, Text

    Zrušení Storno

    První textové pole

    Name, Text

    Zdrojový soubor, ""

    Druhé textové pole

    Name, Text

    CompareString, ""

    Třetí textové pole

    Name, Text

    WordsCounted "0"

    Čtvrté textové pole

    Name, Text

    LinesCounted "0"

  4. Přidání popisku vedle každého textového pole.Nastavit Text vlastnosti pro každý štítek, jak je uvedeno v následující tabulce.

    Objekt

    Property

    Nastavení

    První štítek

    Text

    Zdrojový soubor

    Druhý popisek

    Text

    Porovnání řetězce

    Třetí popisek

    Text

    Odpovídající slova

    Čtvrtý popisek

    Text

    Počítáno řádky

Vytvořte komponentu BackgroundWorker a k jeho události odběru

  1. Přidat BackgroundWorker komponenta součásti sekce nástrojů do formuláře.Zobrazí se na hlavním součást formuláře.

  2. Nastavit následující vlastnosti pro objekt BackgroundWorker1 v Visual Basic nebo backgroundWorker1 objektu v jazyce C#.

    Property

    Nastavení

    WorkerReportsProgress

    True

    WorkerSupportsCancellation

    True

  3. C# pouze odběru události objektu backgroundWorker1.V horní části Vlastnosti okna, klepněte události ikonu.Poklepejte RunWorkerCompleted událostí vytvořit metodu obslužnou rutinu události.Postup ProgressChanged a DoWork události.

Definovat metodu, která bude spuštěna v odděleném podprocesu

  1. Z projektu nabídce zvolte Přidat třídu přidat třídy do projektu.Zobrazí se dialogové okno Přidat novou položku.

  2. Vyberte třídy z okna šablony a typ Words.vb nebo Words.cs v poli název.

  3. Klikněte na tlačítko Přidat.Words Třídy je zobrazen.

  4. Přidejte následující kód Words třídy:

    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;
        }
    
    }
    

Zpracování události z podprocesu

  • Přidejte následující obslužné rutiny událostí hlavního formuláře:

    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();
    }
    

Start a nový podproces, který spustí metodu WordCount volání

  1. Program přidáte následující postupy:

    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);
    }
    
  2. Volání StartThread metoda z Start tlačítko ve formuláři:

    Private Sub Start_Click() Handles Start.Click
        StartThread()
    End Sub
    
    private void Start_Click(object sender, EventArgs e)
    {
        StartThread();
    }
    

Tlačítko Storno, přestane podproces provádění

  • Volání StopThread z postupu Click obslužnou rutinu události pro Cancel tlačítko.

    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();
    }
    

Testování

Nyní můžete otestovat aplikace a zkontrolovat zda funguje správně.

Testování aplikace

  1. Stisknutím klávesy F5 spustíte aplikaci.

  2. Při zobrazení formuláře zadejte cestu k souboru pro soubor, který chcete testovat v sourceFile pole.Za předpokladu, že testovací soubor s názvem: Test.txt, zadejte například C:\Test.txt.

  3. V druhé textové pole zadejte slovo nebo frázi pro aplikaci do textového souboru.

  4. Klikněte na tlačítko Start.LinesCounted Tlačítko začít okamžitě stovce.Aplikace se zobrazí zpráva "Počítání dokončeno" je posláno.

Testování tlačítka Storno

  1. Stisknutím klávesy F5 spustit aplikaci a zadat soubor název a hledat slovo předchozího postupu.Přesvědčte, zda zvolený soubor dostatečně velký na to, zda že máte čas zrušit postup před dokončením.

  2. Klepněte Start tlačítko spustit aplikaci.

  3. Klikněte na tlačítko Cancel.Aplikace by měla přestat okamžitě počítání.

Další kroky

Tato aplikace obsahuje některé základní chyba zpracování.Rozpoznání prázdné vyhledávací řetězce.Robustnější tohoto programu můžete provést pomocí zpracování další chyby, jako je například překročení maximálního počtu slov nebo řádků, které mohou být započítány.

Viz také

Úkoly

Návod: Vytvoření jednoduché vícevláknové komponenty pomocí sady Visual Basic

Postupy: Přihlášení a odhlášení odběru událostí (Průvodce programováním v C#)

Další zdroje

Dělení na vlákna (C# and Visual Basic)