次の方法で共有


方法 : バックグラウンドでファイルをダウンロードする

ファイルのダウンロードは一般的なタスクです。この操作には時間がかかることも多いので、独立したスレッドで実行する方がよい場合があります。 BackgroundWorker コンポーネントを使用すると、わずかなコードのみでこのタスクを行うことができます。

使用例

次のコード例は、BackgroundWorker コンポーネントを使用して URL から XML ファイルを読み込む方法を示します。 ユーザーが [ダウンロード] ボタンをクリックすると、Click イベント ハンドラーによって BackgroundWorker コンポーネントの RunWorkerAsync メソッドが呼び出され、このメソッドによってダウンロードが開始されます。 このボタンは、ダウンロード中は無効になり、ダウンロードが完了すると有効になります。 MessageBox にファイルの内容が表示されます。

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 downloadButton As Button
    Private WithEvents progressBar1 As ProgressBar
    Private WithEvents backgroundWorker1 As BackgroundWorker
    Private document As XmlDocument = Nothing

    Public Sub New()
        InitializeComponent()
        Me.backgroundWorker1 = New System.ComponentModel.BackgroundWorker()
    End Sub

    Private Sub downloadButton_Click( _
        ByVal sender As Object, _
        ByVal e As EventArgs) _
        Handles downloadButton.Click

        ' Start the download operation in the background.
        Me.backgroundWorker1.RunWorkerAsync()

        ' Disable the button for the duration of the download.
        Me.downloadButton.Enabled = False

        ' Once you have started the background thread you 
        ' can exit the handler and the application will 
        ' wait until the RunWorkerCompleted event is raised.

        ' If you want to do something else in the main thread,
        ' such as update a progress bar, you can do so in a loop 
        ' while checking IsBusy to see if the background task is
        ' still running.
        While Me.backgroundWorker1.IsBusy
            progressBar1.Increment(1)
            ' Keep UI messages moving, so the form remains 
            ' responsive during the asynchronous operation.
            Application.DoEvents()
        End While
    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( _
        ByVal sender As Object, _
        ByVal e As RunWorkerCompletedEventArgs) _
        Handles backgroundWorker1.RunWorkerCompleted

        ' Set progress bar to 100% in case it isn't already there.
        progressBar1.Value = 100

        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

        ' Enable the download button and reset the progress bar.
        Me.downloadButton.Enabled = True
        progressBar1.Value = 0
    End Sub

#Region "Windows Form Designer generated code"
    ' <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(ByVal disposing As Boolean)
        If disposing AndAlso (components IsNot Nothing) Then
            components.Dispose()
        End If
        MyBase.Dispose(disposing)
    End Sub

    ' <summary>
    ' Required method for Designer support - do not modify
    ' the contents of this method with the code editor.
    ' </summary>
    Private Sub InitializeComponent()
        Me.downloadButton = New System.Windows.Forms.Button
        Me.progressBar1 = New System.Windows.Forms.ProgressBar
        Me.SuspendLayout()
        '
        'downloadButton
        '
        Me.downloadButton.Location = New System.Drawing.Point(12, 12)
        Me.downloadButton.Name = "downloadButton"
        Me.downloadButton.Size = New System.Drawing.Size(100, 23)
        Me.downloadButton.TabIndex = 0
        Me.downloadButton.Text = "Download file"
        Me.downloadButton.UseVisualStyleBackColor = True
        '
        'progressBar1
        '
        Me.progressBar1.Location = New System.Drawing.Point(12, 50)
        Me.progressBar1.Name = "progressBar1"
        Me.progressBar1.Size = New System.Drawing.Size(100, 26)
        Me.progressBar1.TabIndex = 1
        '
        'Form1
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(136, 104)
        Me.Controls.Add(Me.downloadButton)
        Me.Controls.Add(Me.progressBar1)
        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 downloadButton;
    private ProgressBar progressBar1;
    private XmlDocument document = null;

    public Form1()
    {
        InitializeComponent();

        // Instantiate BackgroundWorker and attach handlers to its
        // DowWork and RunWorkerCompleted events.
        backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
        backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker1_DoWork);
        backgroundWorker1.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker1_RunWorkerCompleted);
    }

    private void downloadButton_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.downloadButton.Enabled = false;

        // Once you have started the background thread you 
        // can exit the handler and the application will 
        // wait until the RunWorkerCompleted event is raised.

        // Or if you want to do something else in the main thread,
        // such as update a progress bar, you can do so in a loop 
        // while checking IsBusy to see if the background task is
        // still running.

        while (this.backgroundWorker1.IsBusy)
        {
            progressBar1.Increment(1);
            // Keep UI messages moving, so the form remains 
            // responsive during the asynchronous operation.
            Application.DoEvents();
        }
    }

    private void backgroundWorker1_DoWork(
        object sender,
        DoWorkEventArgs e)
    {
        document = new XmlDocument();

        // Uncomment the following line to
        // simulate a noticeable latency.
        //Thread.Sleep(5000);

        // Replace this file name with a valid file name.
        document.Load(@"http://www.tailspintoys.com/sample.xml");
    }

    private void backgroundWorker1_RunWorkerCompleted(
        object sender,
        RunWorkerCompletedEventArgs e)
    {
        // Set progress bar to 100% in case it's not already there.
        progressBar1.Value = 100;

        if (e.Error == null)
        {
            MessageBox.Show(document.InnerXml, "Download Complete");
        }
        else
        {
            MessageBox.Show(
                "Failed to download file",
                "Download failed",
                MessageBoxButtons.OK,
                MessageBoxIcon.Error);
        }

        // Enable the download button and reset the progress bar.
        this.downloadButton.Enabled = true;
        progressBar1.Value = 0;
    }

    #region Windows Form Designer generated code

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

    /// <summary>
    /// Required method for Designer support
    /// </summary>
    private void InitializeComponent()
    {
        this.downloadButton = new System.Windows.Forms.Button();
        this.progressBar1 = new System.Windows.Forms.ProgressBar();
        this.SuspendLayout();
        // 
        // downloadButton
        // 
        this.downloadButton.Location = new System.Drawing.Point(12, 12);
        this.downloadButton.Name = "downloadButton";
        this.downloadButton.Size = new System.Drawing.Size(100, 23);
        this.downloadButton.TabIndex = 0;
        this.downloadButton.Text = "Download file";
        this.downloadButton.UseVisualStyleBackColor = true;
        this.downloadButton.Click += new System.EventHandler(this.downloadButton_Click);
        // 
        // progressBar1
        // 
        this.progressBar1.Location = new System.Drawing.Point(12, 50);
        this.progressBar1.Name = "progressBar1";
        this.progressBar1.Size = new System.Drawing.Size(100, 26);
        this.progressBar1.TabIndex = 1;
        // 
        // Form1
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(133, 104);
        this.Controls.Add(this.progressBar1);
        this.Controls.Add(this.downloadButton);
        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 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();

    // Uncomment the following line to
    // simulate a noticeable latency.
    //Thread.Sleep(5000);

    // Replace this file name with a valid file name.
    document.Load(@"http://www.tailspintoys.com/sample.xml");
}

BackgroundWorker の終了の待機

downloadButton_Click イベント ハンドラーは、BackgroundWorker コンポーネントが非同期タスクを完了するまでの待機方法を示します。

バックグラウンド スレッドの完了を待機している間、イベントへの応答だけをアプリケーションで実行し、メイン スレッドでは何も処理を行わないようにする場合は、ハンドラーを終了します。

メイン スレッドで処理を続行する場合は、IsBusy プロパティを使用すると、BackgroundWorker スレッドがまだ実行中かどうかを確認できます。 この例では、ダウンロードの処理中にプログレス バーが更新されます。 UI の応答性を保つために、必ず Application.DoEvents メソッドを呼び出すようにします。

Private Sub downloadButton_Click( _
    ByVal sender As Object, _
    ByVal e As EventArgs) _
    Handles downloadButton.Click

    ' Start the download operation in the background.
    Me.backgroundWorker1.RunWorkerAsync()

    ' Disable the button for the duration of the download.
    Me.downloadButton.Enabled = False

    ' Once you have started the background thread you 
    ' can exit the handler and the application will 
    ' wait until the RunWorkerCompleted event is raised.

    ' If you want to do something else in the main thread,
    ' such as update a progress bar, you can do so in a loop 
    ' while checking IsBusy to see if the background task is
    ' still running.
    While Me.backgroundWorker1.IsBusy
        progressBar1.Increment(1)
        ' Keep UI messages moving, so the form remains 
        ' responsive during the asynchronous operation.
        Application.DoEvents()
    End While
End Sub
private void downloadButton_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.downloadButton.Enabled = false;

    // Once you have started the background thread you 
    // can exit the handler and the application will 
    // wait until the RunWorkerCompleted event is raised.

    // Or if you want to do something else in the main thread,
    // such as update a progress bar, you can do so in a loop 
    // while checking IsBusy to see if the background task is
    // still running.

    while (this.backgroundWorker1.IsBusy)
    {
        progressBar1.Increment(1);
        // Keep UI messages moving, so the form remains 
        // responsive during the asynchronous operation.
        Application.DoEvents();
    }
}

結果の表示

backgroundWorker1_RunWorkerCompleted メソッドは、RunWorkerCompleted イベントを処理するもので、バックグラウンド操作が完了したときに呼び出されます。 このメソッドでは、最初に AsyncCompletedEventArgs.Error プロパティをチェックします。 AsyncCompletedEventArgs.Error が null の場合、このメソッドはファイルの内容を表示します。 その後、ダウンロードの開始時に無効にされたダウンロード ボタンを有効にし、プログレス バーをリセットします。

Private Sub backgroundWorker1_RunWorkerCompleted( _
    ByVal sender As Object, _
    ByVal e As RunWorkerCompletedEventArgs) _
    Handles backgroundWorker1.RunWorkerCompleted

    ' Set progress bar to 100% in case it isn't already there.
    progressBar1.Value = 100

    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

    ' Enable the download button and reset the progress bar.
    Me.downloadButton.Enabled = True
    progressBar1.Value = 0
End Sub
private void backgroundWorker1_RunWorkerCompleted(
    object sender,
    RunWorkerCompletedEventArgs e)
{
    // Set progress bar to 100% in case it's not already there.
    progressBar1.Value = 100;

    if (e.Error == null)
    {
        MessageBox.Show(document.InnerXml, "Download Complete");
    }
    else
    {
        MessageBox.Show(
            "Failed to download file",
            "Download failed",
            MessageBoxButtons.OK,
            MessageBoxIcon.Error);
    }

    // Enable the download button and reset the progress bar.
    this.downloadButton.Enabled = true;
    progressBar1.Value = 0;
}

コードのコンパイル

この例には、次の項目が必要です。

  • System.Drawing、System.Windows.Forms、System.Xml の各アセンブリへの参照。

Visual Basic または Visual C# のコマンド ラインからこの例をビルドする方法の詳細については、「コマンド ラインからのビルド (Visual Basic)」または「csc.exe を使用したコマンド ラインからのビルド」を参照してください。 Visual Studio で新しいプロジェクトにコードを貼り付けてこの例をビルドすることもできます。 詳細については 方法 : 完成した Windows フォーム コードの例を Visual Studio を使ってコンパイルして実行する および 方法 : 完成した Windows フォーム コードの例を Visual Studio を使ってコンパイルして実行する および 方法 : 完成した Windows フォーム コードの例を Visual Studio を使ってコンパイルして実行する および 方法 : 完成した Windows フォーム コードの例を Visual Studio を使ってコンパイルして実行する および 方法 : 完成した Windows フォーム コードの例を Visual Studio を使ってコンパイルして実行する.

信頼性の高いプログラミング

RunWorkerCompletedEventArgs.Result プロパティ、または DoWork イベント ハンドラーの影響を受けている可能性のあるその他のオブジェクトにアクセスする場合は、その前に必ず RunWorkerCompleted イベント ハンドラーで AsyncCompletedEventArgs.Error プロパティをチェックしてください。

参照

処理手順

方法 : バックグラウンドで操作を実行する

方法 : バックグラウンド操作を使用するフォームを実装する

参照

BackgroundWorker