Procedura dettagliata: esecuzione di un'operazione in background

Se l'esecuzione di un'operazione richiede molto tempo e si vogliono evitare ritardi nella risposta dell'interfaccia utente, è possibile usare la classe BackgroundWorker per eseguire l'operazione in un altro thread.

Per un elenco completo del codice usato in questo esempio, vedere Procedura: Eseguire un'operazione in background.

Eseguire un'operazione in background

  1. Con il modulo attivo nella finestra di progettazione Windows Form in Visual Studio, trascinare due Button controlli dalla casella degli strumenti al form e quindi impostare le Name proprietà e Text dei pulsanti in base alla tabella seguente.

    Pulsante Nome Testo
    button1 startBtn Avviare
    button2 cancelBtn Annulla
  2. Aprire la casella degli strumenti, fare clic sulla scheda Componenti e quindi trascinare il BackgroundWorker componente nel form.

    Il backgroundWorker1 componente viene visualizzato nella barra dei componenti.

  3. Nella finestra Proprietà impostare la proprietà WorkerSupportsCancellation su true.

  4. Nella finestra Proprietà fare clic sul pulsante Eventi e quindi fare doppio clic sugli DoWork eventi e RunWorkerCompleted per creare gestori eventi.

  5. Inserire il codice che richiede molto tempo nel DoWork gestore eventi.

  6. Estrarre tutti i parametri richiesti dall'operazione dalla Argument proprietà del DoWorkEventArgs parametro .

  7. Assegnare il risultato del calcolo alla Result proprietà dell'oggetto DoWorkEventArgs.

    Sarà disponibile per il RunWorkerCompleted gestore eventi.

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        // Do not access the form's BackgroundWorker reference directly.
        // Instead, use the reference provided by the sender parameter.
        BackgroundWorker bw = sender as BackgroundWorker;
    
        // Extract the argument.
        int arg = (int)e.Argument;
    
        // Start the time-consuming operation.
        e.Result = TimeConsumingOperation(bw, arg);
    
        // If the operation was canceled by the user,
        // set the DoWorkEventArgs.Cancel property to true.
        if (bw.CancellationPending)
        {
            e.Cancel = true;
        }
    }
    
    Private Sub backgroundWorker1_DoWork( _
    sender As Object, e As DoWorkEventArgs) _
    Handles backgroundWorker1.DoWork
    
       ' Do not access the form's BackgroundWorker reference directly.
       ' Instead, use the reference provided by the sender parameter.
       Dim bw As BackgroundWorker = CType( sender, BackgroundWorker )
       
       ' Extract the argument.
       Dim arg As Integer = Fix(e.Argument)
       
       ' Start the time-consuming operation.
       e.Result = TimeConsumingOperation(bw, arg)
       
       ' If the operation was canceled by the user, 
       ' set the DoWorkEventArgs.Cancel property to true.
       If bw.CancellationPending Then
          e.Cancel = True
       End If
    
    End Sub   
    
  8. Inserire il codice per recuperare il risultato dell'operazione nel RunWorkerCompleted gestore eventi.

    // This event handler demonstrates how to interpret
    // the outcome of the asynchronous operation implemented
    // in the DoWork event handler.
    private void backgroundWorker1_RunWorkerCompleted(
        object sender,
        RunWorkerCompletedEventArgs e)
    {
        if (e.Cancelled)
        {
            // The user canceled the operation.
            MessageBox.Show("Operation was canceled");
        }
        else if (e.Error != null)
        {
            // There was an error during the operation.
            string msg = String.Format("An error occurred: {0}", e.Error.Message);
            MessageBox.Show(msg);
        }
        else
        {
            // The operation completed normally.
            string msg = String.Format("Result = {0}", e.Result);
            MessageBox.Show(msg);
        }
    }
    
    ' This event handler demonstrates how to interpret 
    ' the outcome of the asynchronous operation implemented
    ' in the DoWork event handler.
    Private Sub backgroundWorker1_RunWorkerCompleted( _
    sender As Object, e As RunWorkerCompletedEventArgs) _
    Handles backgroundWorker1.RunWorkerCompleted
    
       If e.Cancelled Then
          ' The user canceled the operation.
          MessageBox.Show("Operation was canceled")
       ElseIf (e.Error IsNot Nothing) Then
          ' There was an error during the operation.
          Dim msg As String = String.Format("An error occurred: {0}", e.Error.Message)
          MessageBox.Show(msg)
       Else
          ' The operation completed normally.
          Dim msg As String = String.Format("Result = {0}", e.Result)
          MessageBox.Show(msg)
       End If
    End Sub   
    
  9. Implementa il metodo TimeConsumingOperation.

    // This method models an operation that may take a long time
    // to run. It can be cancelled, it can raise an exception,
    // or it can exit normally and return a result. These outcomes
    // are chosen randomly.
    private int TimeConsumingOperation(
        BackgroundWorker bw,
        int sleepPeriod )
    {
        int result = 0;
    
        Random rand = new Random();
    
        while (!bw.CancellationPending)
        {
            bool exit = false;
    
            switch (rand.Next(3))
            {
                // Raise an exception.
                case 0:
                {
                    throw new Exception("An error condition occurred.");
                    break;
                }
    
                // Sleep for the number of milliseconds
                // specified by the sleepPeriod parameter.
                case 1:
                {
                    Thread.Sleep(sleepPeriod);
                    break;
                }
    
                // Exit and return normally.
                case 2:
                {
                    result = 23;
                    exit = true;
                    break;
                }
    
                default:
                {
                    break;
                }
            }
    
            if( exit )
            {
                break;
            }
        }
    
        return result;
    }
    
    ' This method models an operation that may take a long time 
    ' to run. It can be cancelled, it can raise an exception,
    ' or it can exit normally and return a result. These outcomes
    ' are chosen randomly.
    Private Function TimeConsumingOperation( _
    bw As BackgroundWorker, _
    sleepPeriod As Integer) As Integer
    
       Dim result As Integer = 0
       
       Dim rand As New Random()
       
         While Not bw.CancellationPending
             Dim [exit] As Boolean = False
    
             Select Case rand.Next(3)
                 ' Raise an exception.
                 Case 0
                     Throw New Exception("An error condition occurred.")
                     Exit While
    
                     ' Sleep for the number of milliseconds
                     ' specified by the sleepPeriod parameter.
                 Case 1
                     Thread.Sleep(sleepPeriod)
                     Exit While
    
                     ' Exit and return normally.
                 Case 2
                     result = 23
                     [exit] = True
                     Exit While
    
                 Case Else
                     Exit While
             End Select
    
             If [exit] Then
                 Exit While
             End If
         End While
       
       Return result
    End Function
    
  10. Nella finestra di progettazione Windows Form fare doppio clic startButton per creare il Click gestore eventi.

  11. Chiamare il RunWorkerAsync metodo nel Click gestore eventi per startButton.

    private void startBtn_Click(object sender, EventArgs e)
    {
        this.backgroundWorker1.RunWorkerAsync(2000);
    }
    
    Private Sub startButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles startBtn.Click
        Me.backgroundWorker1.RunWorkerAsync(2000)
    End Sub
    
  12. Nella finestra di progettazione Windows Form fare doppio clic cancelButton per creare il Click gestore eventi.

  13. Chiamare il CancelAsync metodo nel Click gestore eventi per cancelButton.

    private void cancelBtn_Click(object sender, EventArgs e)
    {
        this.backgroundWorker1.CancelAsync();
    }
    
    Private Sub cancelButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles cancelBtn.Click
        Me.backgroundWorker1.CancelAsync()
    End Sub
    
  14. Nella parte superiore del file importare gli spazi dei nomi System.ComponentModel e System.Threading.

    using System;
    using System.ComponentModel;
    using System.Drawing;
    using System.Threading;
    using System.Windows.Forms;
    
    Imports System.ComponentModel
    Imports System.Drawing
    Imports System.Threading
    Imports System.Windows.Forms
    
  15. Premere F6 per compilare la soluzione, quindi premere CTRL+F5 per eseguire l'applicazione all'esterno del debugger.

    Nota

    Se si preme F5 per eseguire l'applicazione nel debugger, l'eccezione generata nel TimeConsumingOperation metodo viene intercettata e visualizzata dal debugger. Quando si esegue l'applicazione all'esterno del debugger, gestisce BackgroundWorker l'eccezione e la memorizza nella cache nella Error proprietà dell'oggetto RunWorkerCompletedEventArgs.

  16. Fare clic sul pulsante Start per eseguire un'operazione asincrona e quindi sul pulsante Annulla per arrestare un'operazione asincrona in esecuzione.

    Il risultato di ciascuna operazione viene visualizzato in una finestra di messaggio MessageBox.

Passaggi successivi

Vedi anche