Procedura: scaricare file in background
Aggiornamento: novembre 2007
Il download di file è un'attività comune. Spesso è utile eseguire questa operazione potenzialmente dispendiosa in termini di tempo in un thread separato. Utilizzare il componente BackgroundWorker per eseguire questa attività con una quantità di codice molto ridotta.
Esempio
Nell'esempio di codice riportato di seguito è illustrato l'utilizzo di un componente BackgroundWorker per caricare un file XML da un URL. Quando l'utente sceglie il pulsante Download, il gestore eventi Click chiama il metodo RunWorkerAsync di un componente BackgroundWorker per avviare l'operazione di download. Il pulsante è disattivato per la durata del download e quindi abilitato una volta che il download è completato. La classe MessageBox consente di visualizzare il contenuto del file.
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Drawing
Imports System.Threading
Imports System.Windows.Forms
Imports System.Xml
Public Class Form1
Inherits Form
Private WithEvents backgroundWorker1 As BackgroundWorker
Private WithEvents dowloadButton As Button
Private document As XmlDocument = Nothing
Public Sub New()
InitializeComponent()
End Sub
Private Sub dowloadButton_Click( _
ByVal sender As Object, _
ByVal e As EventArgs) _
Handles dowloadButton.Click
' Start the download operation in the background.
Me.backgroundWorker1.RunWorkerAsync()
' Disable the button for the duration of the download.
Me.dowloadButton.Enabled = False
' Wait for the BackgroundWorker to finish the download.
While Me.backgroundWorker1.IsBusy
' Keep UI messages moving, so the form remains
' responsive during the asynchronous operation.
Application.DoEvents()
End While
' The download is done, so enable the button.
Me.dowloadButton.Enabled = True
End Sub
Private Sub backgroundWorker1_DoWork( _
ByVal sender As Object, _
ByVal e As DoWorkEventArgs) _
Handles backgroundWorker1.DoWork
document = New XmlDocument()
' Replace this file name with a valid file name.
document.Load("http://www.tailspintoys.com/sample.xml")
' Uncomment the following line to
' simulate a noticeable latency.
'Thread.Sleep(5000);
End Sub
Private Sub backgroundWorker1_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles backgroundWorker1.RunWorkerCompleted
If e.Error Is Nothing Then
MessageBox.Show(document.InnerXml, "Download Complete")
Else
MessageBox.Show("Failed to download file", "Download failed", MessageBoxButtons.OK, MessageBoxIcon.Error)
End If
End Sub
' <summary>
' Required designer variable.
' </summary>
Private components As System.ComponentModel.IContainer = Nothing
' <summary>
' Clean up any resources being used.
' </summary>
' <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
Protected Overrides Sub Dispose(disposing As Boolean)
If disposing AndAlso (components IsNot Nothing) Then
components.Dispose()
End If
MyBase.Dispose(disposing)
End Sub
#Region "Windows Form Designer generated code"
' <summary>
' Required method for Designer support - do not modify
' the contents of this method with the code editor.
' </summary>
Private Sub InitializeComponent()
Me.backgroundWorker1 = New System.ComponentModel.BackgroundWorker()
Me.dowloadButton = New System.Windows.Forms.Button()
Me.SuspendLayout()
'
' backgroundWorker1
'
'
' dowloadButton
'
Me.dowloadButton.Location = New System.Drawing.Point(12, 12)
Me.dowloadButton.Name = "dowloadButton"
Me.dowloadButton.Size = New System.Drawing.Size(75, 23)
Me.dowloadButton.TabIndex = 0
Me.dowloadButton.Text = "Download file"
Me.dowloadButton.UseVisualStyleBackColor = True
'
' Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6F, 13F)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(104, 54)
Me.Controls.Add(dowloadButton)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
End Sub
#End Region
End Class
Public Class Program
' <summary>
' The main entry point for the application.
' </summary>
<STAThread()> _
Shared Sub Main()
Application.EnableVisualStyles()
Application.Run(New Form1())
End Sub
End Class
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
using System.Xml;
public class Form1 : Form
{
private BackgroundWorker backgroundWorker1;
private Button dowloadButton;
private XmlDocument document = null;
public Form1()
{
InitializeComponent();
}
private void dowloadButton_Click(object sender, EventArgs e)
{
// Start the download operation in the background.
this.backgroundWorker1.RunWorkerAsync();
// Disable the button for the duration of the download.
this.dowloadButton.Enabled = false;
// Wait for the BackgroundWorker to finish the download.
while (this.backgroundWorker1.IsBusy)
{
// Keep UI messages moving, so the form remains
// responsive during the asynchronous operation.
Application.DoEvents();
}
// The download is done, so enable the button.
this.dowloadButton.Enabled = true;
}
private void backgroundWorker1_DoWork(
object sender,
DoWorkEventArgs e)
{
document = new XmlDocument();
// Replace this file name with a valid file name.
document.Load(@"http://www.tailspintoys.com/sample.xml");
// Uncomment the following line to
// simulate a noticeable latency.
//Thread.Sleep(5000);
}
private void backgroundWorker1_RunWorkerCompleted(
object sender,
RunWorkerCompletedEventArgs e)
{
if (e.Error == null)
{
MessageBox.Show(document.InnerXml, "Download Complete");
}
else
{
MessageBox.Show(
"Failed to download file",
"Download failed",
MessageBoxButtons.OK,
MessageBoxIcon.Error );
}
}
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
this.dowloadButton = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// backgroundWorker1
//
this.backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker1_DoWork);
this.backgroundWorker1.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker1_RunWorkerCompleted);
//
// dowloadButton
//
this.dowloadButton.Location = new System.Drawing.Point(12, 12);
this.dowloadButton.Name = "dowloadButton";
this.dowloadButton.Size = new System.Drawing.Size(75, 23);
this.dowloadButton.TabIndex = 0;
this.dowloadButton.Text = "Download file";
this.dowloadButton.UseVisualStyleBackColor = true;
this.dowloadButton.Click += new System.EventHandler(this.dowloadButton_Click);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(104, 54);
this.Controls.Add(this.dowloadButton);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion
}
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}
}
Download di file
Il download dei file viene eseguito nel thread di lavoro del componente BackgroundWorker, che esegue il gestore eventi DoWork. Questo thread inizia nel momento in cui il codice chiama il metodo RunWorkerAsync.
Private Sub backgroundWorker1_DoWork( _
ByVal sender As Object, _
ByVal e As DoWorkEventArgs) _
Handles backgroundWorker1.DoWork
document = New XmlDocument()
' Replace this file name with a valid file name.
document.Load("http://www.tailspintoys.com/sample.xml")
' Uncomment the following line to
' simulate a noticeable latency.
'Thread.Sleep(5000);
End Sub
private void backgroundWorker1_DoWork(
object sender,
DoWorkEventArgs e)
{
document = new XmlDocument();
// Replace this file name with a valid file name.
document.Load(@"http://www.tailspintoys.com/sample.xml");
// Uncomment the following line to
// simulate a noticeable latency.
//Thread.Sleep(5000);
}
Attesa della fine di un BackgroundWorker
Il gestore eventi dowloadButton_Click illustra come viene atteso il completamento di un'attività asincrona da parte di un componente BackgroundWorker. Utilizzare la proprietà IsBusy per determinare se il thread BackgroundWorker è ancora in esecuzione. Se il codice è contenuto nel thread principale dell'interfaccia utente, come nel caso del gestore eventi Click, chiamare il metodo Application.DoEvents per mantenere reattiva l'interfaccia utente.
Private Sub dowloadButton_Click( _
ByVal sender As Object, _
ByVal e As EventArgs) _
Handles dowloadButton.Click
' Start the download operation in the background.
Me.backgroundWorker1.RunWorkerAsync()
' Disable the button for the duration of the download.
Me.dowloadButton.Enabled = False
' Wait for the BackgroundWorker to finish the download.
While Me.backgroundWorker1.IsBusy
' Keep UI messages moving, so the form remains
' responsive during the asynchronous operation.
Application.DoEvents()
End While
' The download is done, so enable the button.
Me.dowloadButton.Enabled = True
End Sub
private void dowloadButton_Click(object sender, EventArgs e)
{
// Start the download operation in the background.
this.backgroundWorker1.RunWorkerAsync();
// Disable the button for the duration of the download.
this.dowloadButton.Enabled = false;
// Wait for the BackgroundWorker to finish the download.
while (this.backgroundWorker1.IsBusy)
{
// Keep UI messages moving, so the form remains
// responsive during the asynchronous operation.
Application.DoEvents();
}
// The download is done, so enable the button.
this.dowloadButton.Enabled = true;
}
Visualizzazione del risultato
Il metodo backgroundWorker1_RunWorkerCompleted gestisce l'evento RunWorkerCompleted e viene chiamato quando l'operazione in background viene completata. Viene verificata la proprietà AsyncCompletedEventArgs.Error e, se è null, viene visualizzato il contenuto del file.
Private Sub backgroundWorker1_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles backgroundWorker1.RunWorkerCompleted
If e.Error Is Nothing Then
MessageBox.Show(document.InnerXml, "Download Complete")
Else
MessageBox.Show("Failed to download file", "Download failed", MessageBoxButtons.OK, MessageBoxIcon.Error)
End If
End Sub
private void backgroundWorker1_RunWorkerCompleted(
object sender,
RunWorkerCompletedEventArgs e)
{
if (e.Error == null)
{
MessageBox.Show(document.InnerXml, "Download Complete");
}
else
{
MessageBox.Show(
"Failed to download file",
"Download failed",
MessageBoxButtons.OK,
MessageBoxIcon.Error );
}
}
Compilazione del codice
Per questo esempio sono necessari i seguenti requisiti:
- Riferimenti agli assembly System.Drawing, System.Windows.Forms e System.Xml.
Per informazioni sulla generazione di questo esempio dalla riga di comando per Visual Basic o Visual C#, vedere Compilazione dalla riga di comando (Visual Basic) o Compilazione dalla riga di comando con csc.exe. È anche possibile generare questo esempio in Visual Studio incollando il codice in un nuovo progetto.
Programmazione efficiente
Verificare sempre la presenza della proprietà AsyncCompletedEventArgs.Error nel gestore eventi RunWorkerCompleted in uso prima di tentare di accedere alla proprietà RunWorkerCompletedEventArgs.Result o ad eventuali altri oggetti che possano essere influenzati dal gestore eventi DoWork.
Vedere anche
Attività
Procedura: eseguire un'operazione in background
Procedura: implementare un form che utilizza un'operazione in background