Procedura dettagliata: esecuzione di un'operazione in background
Se l'esecuzione di un'operazione richiede molto tempo e si desidera evitare ritardi nella risposta dell'interfaccia utente, è possibile utilizzare la classe BackgroundWorker per eseguire l'operazione in un altro thread.
Per il listato completo del codice utilizzato in questo esempio, vedere Procedura: eseguire un'operazione in background.
Nota
È possibile che le finestre di dialogo e i comandi di menu visualizzati siano diversi da quelli descritti nella Guida a seconda delle impostazioni attive o dell'edizione del programma. Per modificare le impostazioni, scegliere Importa/Esporta impostazioni dal menu Strumenti. Per ulteriori informazioni, vedere Gestione delle impostazioni.
Per eseguire un'operazione in background
Trascinare due controlli Button dalla Casella degli strumenti al form attivo in Progettazione Windows Form, quindi impostare le proprietà Name e Text dei pulsanti secondo i valori indicati nella tabella seguente.
Button
Name
Text
button1
startBtn
Start
button2
cancelBtn
Cancel
Aprire la Casella degli strumenti, fare clic sulla scheda Componenti e trascinare il componente BackgroundWorker nel form.
Il componente backgroundWorker1 verrà visualizzato nella Barra dei componenti.
Nella finestra Proprietà impostare la proprietà WorkerSupportsCancellation su true.
Fare clic sul pulsante Eventi nella finestra Proprietà, quindi fare doppio clic sugli eventi DoWork e RunWorkerCompleted per creare i gestori eventi.
Inserire codice particolarmente complesso nel gestore eventi DoWork.
Estrarre tutti i parametri richiesti per l'operazione dalla proprietà Argument del parametro DoWorkEventArgs.
Assegnare il risultato del calcolo alla proprietà Result della classe DoWorkEventArgs.
Il risultato sarà disponibile al gestore eventi RunWorkerCompleted.
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
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; } }
Inserire il codice per recuperare il risultato dell'operazione nel gestore eventi RunWorkerCompleted.
' 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
// 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); } }
Implementare 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 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
// 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; }
In Progettazione Windows Form fare doppio clic su startButton per creare il gestore eventi Click.
Chiamare il metodo RunWorkerAsync nel gestore eventi Click per startButton.
Private Sub startButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles startBtn.Click Me.backgroundWorker1.RunWorkerAsync(2000) End Sub
private void startBtn_Click(object sender, EventArgs e) { this.backgroundWorker1.RunWorkerAsync(2000); }
In Progettazione Windows Form fare doppio clic su cancelButton per creare il gestore eventi Click.
Chiamare il metodo CancelAsync nel gestore eventi Click per cancelButton.
Private Sub cancelButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles cancelBtn.Click Me.backgroundWorker1.CancelAsync() End Sub
private void cancelBtn_Click(object sender, EventArgs e) { this.backgroundWorker1.CancelAsync(); }
All'inizio del file, importare gli spazi dei nomi System.ComponentModel e System.Threading.
Imports System Imports System.ComponentModel Imports System.Drawing Imports System.Threading Imports System.Windows.Forms
using System; using System.ComponentModel; using System.Drawing; using System.Threading; using System.Windows.Forms;
Premere F6 per compilare la soluzione, quindi premere CTRL-F5 per eseguire l'applicazione al di fuori del debugger.
Nota
Se si preme F5 per eseguire l'applicazione all'interno del debugger, l'eccezione generata nel metodo TimeConsumingOperation verrà rilevata e visualizzata dal debugger. Quando si esegue l'applicazione al di fuori del debugger, BackgroundWorker gestisce l'eccezione e la memorizza in cache nella proprietà Error della classe RunWorkerCompletedEventArgs.
Fare clic sul pulsante Start per eseguire un'operazione asincrona, quindi fare clic sul pulsante Annulla per interrompere l'esecuzione.
Il risultato di ciascuna operazione viene visualizzato in una finestra di messaggio MessageBox.
Passaggi successivi
Implementare un form in cui venga indicato lo stato di avanzamento di un'operazione asincrona. Per ulteriori informazioni, vedere Procedura: implementare un form che utilizza un'operazione in background.
Implementare una classe che supporta il modello asincrono per componenti. Per ulteriori informazioni, vedere Implementazione del modello asincrono basato su eventi.
Vedere anche
Attività
Procedura: implementare un form che utilizza un'operazione in background
Procedura: eseguire un'operazione in background