下载文件是常见任务,通常情况下,最好以单独的线程来运行这项可能很耗时的操作。使用 BackgroundWorker 组件可以用非常少的代码完成此任务。
示例:
下面的代码示例演示如何使用 BackgroundWorker 组件从 URL 加载 XML 文件。用户单击“下载”按钮时,Click 事件处理程序将调用 BackgroundWorker 组件的 RunWorkerAsync 方法来启动下载操作。在下载过程中,将禁用该按钮,然后在下载完成后再启用该按钮。MessageBox 将显示文件的内容。
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()); } }
下载文件:
文件下载在 BackgroundWorker 组件的辅助线程上进行,该线程运行 DoWork 事件处理程序。当代码调用 RunWorkerAsync 方法时,将启动此线程。
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); }
等待 BackgroundWorker 完成
dowloadButton_Click 事件处理程序演示如何等待 BackgroundWorker 组件完成它的异步任务。使用 IsBusy 属性可以确定 BackgroundWorker 线程是否仍在运行。如果代码在主 UI 线程上(对于 Click 事件处理程序即是如此),请务必调用 Application.DoEvents 方法以使用户界面能够响应用户操作。
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; }
显示结果
backgroundWorker1_RunWorkerCompleted 方法将处理 RunWorkerCompleted 事件,并在后台操作完成后被调用。它首先检查 AsyncCompletedEventArgs.Error 属性,如果该属性是 null,它将显示文件内容。
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 ); } }