C# BackgroundWorker实现WinForm异步操作的例子

本文介绍BackgroundWorker组件在Windows窗体应用程序中的使用方法,包括如何创建和配置组件、启动后台任务、取消任务、报告进度更新及处理任务完成后的事件。通过两个实例演示了BackgroundWorker在实际场景中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

原文:http://blog.youkuaiyun.com/longlong821/article/details/6613399

BackgroundWorker 类允许您在单独的专用线程上运行操作。耗时的操作(如下载和数据库事务)在长时间运行时可能会导致用户界面 (UI) 似乎处于停止响应状态。如果您需要能进行响应的用户界面,而且面临与这类操作相关的长时间延迟,则可以使用 BackgroundWorker 类方便地解决问题。

若要在后台执行耗时的操作,请创建一个 BackgroundWorker,侦听那些报告操作进度并在操作完成时发出信号的事件。可以通过编程方式创建 BackgroundWorker,也可以将它从“工具箱”的“组件”选项卡中拖到窗体上。如果在 Windows 窗体设计器中创建 BackgroundWorker,则它会出现在组件栏中,而且它的属性会显示在“属性”窗口中。

若要设置后台操作,请为 DoWork 事件添加一个事件处理程序。在此事件处理程序中调用耗时的操作。若要启动该操作,请调用 RunWorkerAsync。若要收到进度更新通知,请对 ProgressChanged 事件进行处理。若要在操作完成时收到通知,请对 RunWorkerCompleted 事件进行处理。

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.ComponentModel;  
  4. using System.Data;  
  5. using System.Drawing;  
  6. using System.Linq;  
  7. using System.Text;  
  8. using System.Windows.Forms;  
  9.   
  10. namespace WindowsFormsApplication2  
  11. {  
  12.     public partial class Form1 : Form  
  13.     {  
  14.         private int numberToCompute = 0;  
  15.         private int highestPercentageReached = 0;  
  16.         public Form1()  
  17.         {  
  18.             InitializeComponent();  
  19.             InitializeBackgoundWorker();  
  20.         }  
  21.   
  22.         private void InitializeBackgoundWorker()  
  23.         {  
  24.             //添加委托   
  25.             backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);  
  26.             //委托完成后执行的事件   
  27.             backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);  
  28.             //执行委托过程中报告进度信息   
  29.             backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);  
  30.         }  
  31.           
  32.   
  33.         private void Form1_Load(object sender, EventArgs e)  
  34.         {  
  35.   
  36.         }  
  37.         //开始异步执行   
  38.         private void startAsyncButton_Click_1(object sender, EventArgs e)  
  39.         {  
  40.             // Reset the text in the result label.   
  41.             resultLabel.Text = String.Empty;  
  42.   
  43.             // Disable the UpDown control until   
  44.             // the asynchronous operation is done.   
  45.             this.numericUpDown1.Enabled = false;  
  46.   
  47.             // Disable the Start button until   
  48.             // the asynchronous operation is done.   
  49.             this.startAsyncButton.Enabled = false;  
  50.   
  51.             // Enable the Cancel button while   
  52.             // the asynchronous operation runs.   
  53.             this.cancelAsyncButton.Enabled = true;  
  54.   
  55.             // Get the value from the UpDown control.   
  56.             numberToCompute = (int)numericUpDown1.Value;  
  57.   
  58.             // Reset the variable for percentage tracking.   
  59.             highestPercentageReached = 0;  
  60.   
  61.             // 使用RunWorkerAsync来激活backgroundWorker1执行   
  62.             backgroundWorker1.RunWorkerAsync(numberToCompute);  
  63.         }  
  64.   
  65.         private void cancelAsyncButton_Click(object sender, EventArgs e)  
  66.         {  
  67.             // Cancel the asynchronous operation.   
  68.             this.backgroundWorker1.CancelAsync();  
  69.             // Disable the Cancel button.   
  70.             cancelAsyncButton.Enabled = false;  
  71.         }  
  72.   
  73.         private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)  
  74.         {  
  75.                
  76.             BackgroundWorker worker = sender as BackgroundWorker;  
  77.               
  78.             //e.Argument接收RunWorkerAsync传递过来的numberToCompute   
  79.             e.Result = ComputeFibonacci((int)e.Argument, worker, e);  
  80.         }  
  81.   
  82.         // This event handler deals with the results of the   
  83.         // background operation.   
  84.         private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)  
  85.         {  
  86.             // First, handle the case where an exception was thrown.   
  87.             if (e.Error != null)  
  88.             {  
  89.                 MessageBox.Show(e.Error.Message);  
  90.             }  
  91.             else if (e.Cancelled)  
  92.             {  
  93.                 // Next, handle the case where the user canceled   
  94.                 // the operation.   
  95.                 // Note that due to a race condition in   
  96.                 // the DoWork event handler, the Cancelled   
  97.                 // flag may not have been set, even though   
  98.                 // CancelAsync was called.   
  99.                 resultLabel.Text = "Canceled";  
  100.             }  
  101.             else  
  102.             {  
  103.                 // Finally, handle the case where the operation   
  104.                 // succeeded.   
  105.                 resultLabel.Text = e.Result.ToString();  
  106.             }  
  107.             // Enable the UpDown control.   
  108.             this.numericUpDown1.Enabled = true;  
  109.             // Enable the Start button.   
  110.             startAsyncButton.Enabled = true;  
  111.             // Disable the Cancel button.   
  112.             cancelAsyncButton.Enabled = false;  
  113.         }  
  114.   
  115.         private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)  
  116.         {  
  117.             this.progressBar1.Value = e.ProgressPercentage;  
  118.         }  
  119.   
  120.   
  121.         long ComputeFibonacci(int n, BackgroundWorker worker, DoWorkEventArgs e)  
  122.         {  
  123.                
  124.             if ((n < 0) || (n > 91))  
  125.             {  
  126.                 throw new ArgumentException("value must be >= 0 and <= 91""n");  
  127.             }  
  128.             long result = 0;  
  129.   
  130.                
  131.             if (worker.CancellationPending)  
  132.             {  
  133.                 e.Cancel = true;  
  134.             }  
  135.             else  
  136.             {  
  137.                 if (n < 2)  
  138.                 {  
  139.                     result = 1;  
  140.                 }  
  141.                 else  
  142.                 {  
  143.                     result = ComputeFibonacci(n - 1, worker, e) + ComputeFibonacci(n - 2, worker, e);  
  144.                 }  
  145.   
  146.                 // Report progress as a percentage of the total task.   
  147.                 int percentComplete = (int)((float)n / (float)numberToCompute * 100);  
  148.                 if (percentComplete > highestPercentageReached)  
  149.                 {  
  150.                     highestPercentageReached = percentComplete;  
  151.                     worker.ReportProgress(percentComplete);  
  152.                 }  
  153.             }  
  154.             return result;  
  155.         }  
  156.   
  157.            
  158.     }  
  159. }  

大撒旦










另外一个例子:一个基于BackgorundWorker的例子。由于这个理基本上实现了BackgorundWorker的大部分功能:异步操作的启动、操作结束后的回调、异步操作的撤销和进度报告等等有两组相互独立的数据需要逐条获取和显示,左边和右边两个groupbox分别代表基于这两组数据的操作,由于他们完全独立,因此可以并行执行。当点击Start按钮,以异步的方式从存储介质中逐条获取数据,并将获取的数据追加到对应的ListBox中,ProgressBar真实反映以获取的数据条数和总记录条数的百分比,同时,当前获取的条数也会在下方的Label上随着操作的继续而动态变化。此外通过点击Stop按钮,可以中止掉当前的操作。当操作被中止后,ProgressBar和Label反映中止的那一刻的状态。

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.ComponentModel;  
  4. using System.Data;  
  5. using System.Drawing;  
  6. using System.Linq;  
  7. using System.Text;  
  8. using System.Windows.Forms;  
  9. using System.Threading;  
  10.   
  11. namespace WindowsFormsApplication2  
  12. {  
  13.     public partial class Form2 : Form  
  14.     {  
  15.         private int ppo = -1;  
  16.         public Form2()  
  17.         {  
  18.             InitializeComponent();  
  19.             InitializeBackgroundWork();  
  20.         }  
  21.         private void InitializeBackgroundWork()  
  22.         {  
  23.             //添加委托   
  24.             backgroundWorker1.DoWork+=new DoWorkEventHandler( backgroundWorker1_DoWork);  
  25.             //委托完成后要执行的事件   
  26.             backgroundWorker1.RunWorkerCompleted+=new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);  
  27.             //进度报告事件   
  28.             backgroundWorker1.ProgressChanged+=new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);  
  29.         }  
  30.   
  31.         private void backgroundWorker1_DoWork(object oj,DoWorkEventArgs e)  
  32.         {  
  33.             try  
  34.             {  
  35.                 ReadData(backgroundWorker1,e);  
  36.             }  
  37.             catch(Exception EX)  
  38.             {  
  39.   
  40.             }  
  41.         }  
  42.   
  43.         private void ReadData(BackgroundWorker work ,DoWorkEventArgs e)  
  44.         {  
  45.               
  46.             for (int i = 0; i < 100; i++)  
  47.             {  
  48.                 if (work.CancellationPending)  
  49.                     return;  
  50.                 work.ReportProgress(i,new KeyValuePair<intstring>(i,Guid.NewGuid().ToString() ));  
  51.                 Thread.Sleep(1000);  
  52.             }  
  53.         }  
  54.   
  55.         private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)  
  56.         {  
  57.             KeyValuePair<int,string> kp=(KeyValuePair<int,string>)e.UserState;  
  58.             if (kp.Key == ppo)  
  59.                 return;  
  60.             else  
  61.                 ppo = kp.Key;  
  62.             listBox1.Items.Add(kp.Value);  
  63.             label1.Text = string.Format("There is have {0} data", kp.Key);  
  64.             progressBar1.Value = e.ProgressPercentage;  
  65.         }  
  66.   
  67.         private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)  
  68.         {  
  69.             label1.Text = string.Format(label1.Text+"   is over!!!");  
  70.             this.end.Enabled = false;  
  71.             this.start.Enabled = true;  
  72.         }  
  73.   
  74.         private void start_Click(object sender, EventArgs e)  
  75.         {  
  76.             this.start.Enabled = false;  
  77.             this.end.Enabled = true;  
  78.             this.label1.Text = "";  
  79.             this.listBox1.Items.Clear();  
  80.             backgroundWorker1.RunWorkerAsync();  
  81.         }  
  82.   
  83.         private void end_Click(object sender, EventArgs e)  
  84.         {  
  85.             backgroundWorker1.CancelAsync();  
  86.             this.end.Enabled = false;  
  87.             this.start.Enabled = true;  
  88.               
  89.         }  
  90.   
  91.           
  92.   
  93.    
  94.     }  
  95. }  


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值