多线程编程

BackgroundWorker 组件概述 

许多经常执行的操作可能需要很长的执行时间。例如:

图像下载

Web 服务调用

文件下载和上载(包括点对点应用程序)

复杂的本地计算

数据库事务

本地磁盘访问(相对于内存访问来说其速度很慢)

类似这样的操作可能导致用户界面在操作运行时挂起。如果您需要用户界面的响应却遇到与此类操作关联的长时间延迟,BackgroundWorker 组件可以提供一种方便的解决方案。

使用 BackgroundWorker 组件,您可以在不同于应用程序的主用户界面线程的另一线程上异步(在后台)执行耗时的操作。若要使用 BackgroundWorker,只需要告诉该组件要在后台执行的耗时的辅助方法,然后调用 RunWorkerAsync 方法。在辅助方法以异步方式运行的同时,您的调用线程继续正常运行。该方法运行完毕,BackgroundWorker 激发 RunWorkerCompleted 事件(可选择包含操作结果)向调用线程发出警报。

组件选项卡的工具箱中提供了 BackgroundWorker 组件。若要向窗体添加 BackgroundWorker,请将 BackgroundWorker 组件拖到窗体上。该组件出现在组件栏中,该组件的属性出现在属性窗口中。

若要启动异步操作,请使用 RunWorkerAsync 方法。RunWorkerAsync 采用一个可选的 object 参数,可以使用该参数将变量传递给辅助方法。BackgroundWorker 类公开 DoWork 事件,您的辅助线程通过 DoWork 事件处理程序附加到该事件。

DoWork 事件处理程序采用一个 DoWorkEventArgs 参数,该参数具有 Argument 属性。此属性接收来自 RunWorkerAsync 的参数,并可以传递至 DoWork 事件处理程序中调用的辅助方法。下面的示例演示如何分配名为 ComputeFibonacci 的辅助方法的结果。该示例摘自如何:实现使用后台操作的窗体中一个较大的示例。
// This event handler is where the actual,
// potentially time-consuming work is done.
private void backgroundWorker1_DoWork(object sender,
    DoWorkEventArgs e)
{  
    // Get the BackgroundWorker that raised this event.
    BackgroundWorker worker = sender as BackgroundWorker;

    // Assign the result of the computation
    // to the Result property of the DoWorkEventArgs
    // object. This is will be available to the
    // RunWorkerCompleted eventhandler.
    e.Result = ComputeFibonacci((int)e.Argument, worker, e);
}
.NET Framework
类库
 
BackgroundWorker.RunWorkerAsync
方法
 
开始执行后台操作。

重载列表

名称  说明 
BackgroundWorker.RunWorkerAsync () 
开始执行后台操作。
 
BackgroundWorker.RunWorkerAsync (Object) 
开始执行后台操作。
 
异常类型 条件

InvalidOperationException
 IsBusy
true

 

备注

RunWorkerAsync 方法提交一个启动以异步方式运行的操作的请求。发出该请求后,将引发 DoWork 事件,该事件随后开始执行后台操作。

如果后台操作已在运行,则再次调用 RunWorkerAsync 将引发 InvalidOperationException

示例

下面的代码示例演示如何使用 RunWorkerAsync 方法启动异步操作。它摘自 如何:在后台下载文件中描述的一个更大示例。

C# 复制到剪贴板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;
}
RunWorkerAsync
方法提交一个启动以异步方式运行的操作的请求。发出该请求后,将引发 DoWork 事件,该事件随后开始执行后台操作。

如果操作需要参数,可以将其作为 argument 参数提供给 RunWorkerAsync

如果后台操作已在运行,则再次调用 RunWorkerAsync 将引发 InvalidOperationException
Start the asynchronous operation.
backgroundWorker1.RunWorkerAsync(System.Convert.ToString(numberToCompute));
BackgroundWorker
属性 

公共属性

  名称  说明 
  CancellationPending 
获取一个值,指示应用程序是否已请求取消后台操作。
 
  Container  
获取 IContainer,它包含 Component。 (从 Component 继承。)
 
  IsBusy 
获取一个值,指示 BackgroundWorker 是否正在运行异步操作。
 
  Site  
获取或设置 Component ISite。 (从 Component 继承。)
 
  WorkerReportsProgress 
获取或设置一个值,该值指示 BackgroundWorker 能否报告进度更新。
 
  WorkerSupportsCancellation 
获取或设置一个值,该值指示 BackgroundWorker 是否支持异步取消。
 
页首

受保护的属性

  名称  说明 
  CanRaiseEvents  
获取一个指示组件是否可以引发事件的值。 (从 Component 继承。)
 
  DesignMode  
获取一个值,用以指示 Component 当前是否处于设计模式。(从 Component 继承。)
 
  Events  
获取附加到此 Component 的事件处理程序的列表。(从 Component 继承。)
 
BackgroundWorker
事件 

公共事件

  名称  说明 
  Disposed  
添加事件处理程序以侦听组件上的 Disposed 事件。(从 Component 继承。)
 
  DoWork 
调用 RunWorkerAsync 时发生。
 
  ProgressChanged 
调用 ReportProgress 时发生。
 
  RunWorkerCompleted 
当后台操作已完成、被取消或引发异常时发生。
 
// This event handler updates the progress bar.
private void backgroundWorker1_ProgressChanged(object sender,
    ProgressChangedEventArgs e)
{
    this.progressBar1.Value = e.ProgressPercentage;
}

// This event handler deals with the results of the
// background operation.
private void backgroundWorker1_RunWorkerCompleted(
    object sender, RunWorkerCompletedEventArgs e)
{
    // First, handle the case where an exception was thrown.
    if (e.Error != null)
    {
        MessageBox.Show(e.Error.Message);
    }
    else if (e.Cancelled)
    {
        // Next, handle the case where the user canceled
        // the operation.
        // Note that due to a race condition in
        // the DoWork event handler, the Cancelled
        // flag may not have been set, even though
        // CancelAsync was called.
        resultLabel.Text = "Canceled";
    }
    else
    {
        // Finally, handle the case where the operation
        // succeeded.
        resultLabel.Text = e.Result.ToString();
    }

    // Enable the UpDown control.
    this.numericUpDown1.Enabled = true;

    // Enable the Start button.
    startAsyncButton.Enabled = true;

    // Disable the Cancel button.
    cancelAsyncButton.Enabled = false;
}
属性值

如果 BackgroundWorker 支持进度更新,则为 true;否则为 false。默认为 false
备注

如果您希望 BackgroundWorker 支持进度更新,请将 WorkerReportsProgress 属性设置为 true。当此属性为 true 时,用户代码可以调用 ReportProgress 方法来引发 ProgressChanged 事件。
如果您需要后台操作报告其进度,则可以调用 ReportProgress 方法来引发 ProgressChanged 事件。WorkerReportsProgress 属性值必须是 true,否则 ReportProgress 将引发 InvalidOperationException

您需要实现一个有意义的方法,以便按照占已完成的总任务的百分比来度量后台操作的进度。

if (worker.CancellationPending)
{  
    e.Cancel = true;
}
else
{  
    if (n < 2)
    {  
        result = 1;
    }
    else
    {  
        result = ComputeFibonacci(n - 1, worker, e) +
                 ComputeFibonacci(n - 2, worker, e);
    }

    // Report progress as a percentage of the total task.
    int percentComplete =
        (int)((float)n / (float)numberToCompute * 100);
    if (percentComplete > highestPercentageReached)
    {
        highestPercentageReached = percentComplete;
        worker.ReportProgress(percentComplete);
    }
}
Application.DoEvents
方法
 
处理当前在消息队列中的所有 Windows 消息。

相当于Delphi
application.Progress;
当运行 Windows 窗体时,它将创建新窗体,然后该窗体等待处理事件。该窗体在每次处理事件时,均将处理与该事件关联的所有代码。所有其他事件在队列中等待。在代码处理事件时,应用程序并不响应。例如,当将另一窗口拖到该窗口前面时,该窗口不重新绘制。

如果在代码中调用 DoEvents,则您的应用程序可以处理其他事件。例如,如果您有向 ListBox 添加数据的窗体,并将 DoEvents 添加到代码中,那么当将另一窗口拖到您的窗体上时,该窗体将重新绘制。如果从代码中移除 DoEvents,那么在按钮的单击事件处理程序执行结束以前,您的窗体不会重新绘制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值