1. 程式人生 > 實用技巧 >C# BackgroundWorker

C# BackgroundWorker

示範:

using System.Windows;
using System.Threading;
using System.ComponentModel;

namespace WpfApp1
{
    /// <summary>
    /// MainWindow.xaml 的互動邏輯
    /// </summary>
    public partial class MainWindow : Window
    {

        private BackgroundWorker bw = new BackgroundWorker(); //宣告BackgroundWorker物件
public MainWindow() { InitializeComponent(); InitBW(); } /// <summary> /// 初始化 /// </summary> private void InitBW() { //屬性 bw.WorkerReportsProgress = true; bw.WorkerSupportsCancellation
= true; //事件 bw.DoWork += Bw_DoWork; bw.ProgressChanged += Bw_ProgressChanged; bw.RunWorkerCompleted += Bw_RunWorkerCompleted; } private void Bw_DoWork(object sender, DoWorkEventArgs e) { //string a = e.Argument as string;
for (int i = 0; i < 100; i++) { //當接收到取消指令時 if (bw.CancellationPending) { e.Cancel = true; return; } else { bw.ReportProgress(i, "Working"); //呼叫ReportProgress方法 Thread.Sleep(10); } } } private void Bw_ProgressChanged(object sender, ProgressChangedEventArgs e) { pro1.Value = e.ProgressPercentage; txt1.Text = e.ProgressPercentage.ToString() + "%"; txt2.Text = e.UserState.ToString(); } private void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { //是否出現錯誤 if (e.Error != null) { MessageBox.Show(e.Error.ToString()); return; } //是否為使用者取消 if (e.Cancelled) { txt1.Text = "終止"; txt2.Text = "Worked"; } else { txt1.Text = "完畢"; txt2.Text = "Worked"; } } //啟動 private void btnStart_Click(object sender, RoutedEventArgs e) { //是否正在執行一個非同步操作 if (bw.IsBusy) return; pro1.Maximum = 100; btnStart.IsEnabled = false; btnStop.IsEnabled = true; bw.RunWorkerAsync("hello world"); } //停止 private void btnStop_Click(object sender, RoutedEventArgs e) { bw.CancelAsync(); btnStart.IsEnabled = true; btnStop.IsEnabled = false; } } }

C#backgroundWorker用法

1、在 WinForms 中,有時要執行耗時的操作,在該操作未完成之前操作使用者介面,會導致使用者介面停止響應。解決的方法就是新開一個執行緒,把耗時的操作放到執行緒中執行,這樣就可以在使用者介面上進行其它操作。新建執行緒可以用 Thread 類,可以實現多執行緒同時操作。簡單的方法可以通過 BackgroundWorker 類實現。

BackgroundWorker 可以用來更新UI介面,但是通常用來Progressbar(進度條)控制元件

例如更新UI

private void Form1_Load(object sender, EventArgs e)
{
      this.backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
       this.textBox1.Text = "UI";
}

用 BackgroundWorker 類執行耗時的操作
BackgroundWorker 類在 System.ComponentModel 名稱空間下。
VS 的工具箱時有一個 BackgroundWorker 元件,就是這個類。

backgroundwork主要的事件及引數:
1.DoWork——當執行BackgroundWorker.RunWorkerAsync方法時會觸發該事件,並且傳遞DoWorkEventArgs引數;

2.RunWorkerCompleted——非同步操作完成或中途終止會觸發該事件。

3.ProgressChanged——操作處理中獲得的處理狀態變化,通過BackgroundWorker.ReportProgress(int)方法觸發該事件,並且傳遞ProgressChangedEventArgs,其中包含了處理的百分比,這個引數在UI介面上設定progressbar控制元件。

backgroundwork主要的方法:
1. BackgroundWorker.RunWorkerAsync——“起動”非同步呼叫的方法有兩次過載RunWorkerAsync(),RunWorkerAsync(object argument),第二個過載提供了一個引數,可以供非同步呼叫使用。(如果有多個引數要傳遞怎麼辦,使用一個類來傳遞他們吧)。呼叫該方法後會觸發DoWork事件。並且為處理DoWork事件的函式傳遞DoWorkEventArg引數,其中包含了RunWorkerAsync傳遞的引數。在相應DoWork的處理函式中就可以做具體的複雜操作。

2. BackgroundWorker.ReportProgress——需要在一個冗長的操作中向用戶不斷反饋進度,這樣的話就可以呼叫的ReportProgress(int percent),在呼叫 ReportProgress 方法時,觸發ProgressChanged事件。提供一個在 0 到 100 之間的整數,它表示後臺活動已完成的百分比。你也可以提供任何物件作為第二個引數,允許你 給事件處理程式傳遞狀態資訊。作為傳遞到此過程的 ProgressChangedEventArgs 引數屬性,百分比和你自己的物件(如果提供的話)均要被傳遞到 ProgressChanged 事件處理程式。這些屬性被分別命名為 ProgressPercentage 和 UserState,並且你的事件處理程式可以以任何需要的方式使用它們。(注意:只有在BackgroundWorker.WorkerReportsProgress屬性被設定為true該方法才可用)。

3. BackgroundWorker.CancelAsync——但需要退出非同步呼叫的時候,就呼叫的這個方法。但是樣還不夠,因為它僅僅是將BackgroudWorker.CancellationPending屬性設定為true。你需要在具體的非同步呼叫處理的時候,不斷檢查BackgroudWorker.CancellationPending是否為true,如果是真的話就退出。(注意:只有在BackgroundWorker.WorkerSupportsCancellation屬性被設定為true該方法才可用)。

BackgroundWorker元件
重要屬性:
1、CancellationPending 獲取一個值,指示應用程式是否已請求取消後臺操作。通過在DoWork事件中判斷CancellationPending屬性可以認定是否需要取消後臺操作(也就是結束執行緒);
2、 WorkerReportsProgress:獲取或設定一個值,該值指示BackgroundWorker能否報告進度更新

重要方法:
1、CancelAsync 請求取消掛起的後臺操作
2、RunWorkerAsync開始執行後臺操作
3、ReportProgress引發ProgressChanged事件

重要事件:
1、DoWork呼叫 RunWorkerAsync 時發生
2、ProgressChanged 呼叫 ReportProgress 時發生
3、RunWorkerCompleted當後臺操作已完成、被取消或引發異常時發生
另外還有三個重要的引數是RunWorkerCompletedEventArgs以及DoWorkEventArgs、ProgressChangedEventArgs。
例子:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Delegate3
{
    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
        }
        
        private void button1_Click(object sender, EventArgs e)
        {
            //啟動非同步呼叫方法
            //呼叫RunWorkerAsync()方法,會觸發DoWork事件
            this.backgroundWorker2.RunWorkerAsync();
        }

        private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
        {
            backgroundWorker2.WorkerReportsProgress = true;
            for (int i = 1; i <= 100; i++)
            {
                //這裡判斷一下是否使用者要求取消後臺進行,並可以儘早退出。
                //可以通過呼叫CancelAsync方法設定CancellationPending的值為false
                if (backgroundWorker2.CancellationPending)
                {
                    backgroundWorker2.ReportProgress(i, String.Format("{0}%,操作被使用者申請中斷", i));
                }

                //呼叫 ReportProgress 方法,會觸發ProgressChanged事件
                backgroundWorker2.ReportProgress(i, String.Format("{0}%", i));
                System.Threading.Thread.Sleep(10);
            }
        }

        private void backgroundWorker2_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.progressBar1.Value = e.ProgressPercentage;
            this.label1.Text = e.UserState.ToString();
            this.label1.Update();
        }

        private void backgroundWorker2_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //這是結束後做的事情
            MessageBox.Show("完成");
        }
    }
}

using System.Windows;using System.Threading;using System.ComponentModel;
namespace WpfApp1{/// <summary>/// MainWindow.xaml 的互動邏輯/// </summary>public partial class MainWindow : Window{
private BackgroundWorker bw = new BackgroundWorker(); //宣告BackgroundWorker物件
public MainWindow(){InitializeComponent();
InitBW();
}
/// <summary>/// 初始化/// </summary>private void InitBW(){//屬性bw.WorkerReportsProgress = true;bw.WorkerSupportsCancellation = true;
//事件bw.DoWork += Bw_DoWork;bw.ProgressChanged += Bw_ProgressChanged;bw.RunWorkerCompleted += Bw_RunWorkerCompleted;}
private void Bw_DoWork(object sender, DoWorkEventArgs e){//string a = e.Argument as string;
for (int i = 0; i < 100; i++){//當接收到取消指令時if (bw.CancellationPending){e.Cancel = true;return;}else{bw.ReportProgress(i, "Working"); //呼叫ReportProgress方法Thread.Sleep(10);}}}
private void Bw_ProgressChanged(object sender, ProgressChangedEventArgs e){pro1.Value = e.ProgressPercentage;txt1.Text = e.ProgressPercentage.ToString() + "%";txt2.Text = e.UserState.ToString();}
private void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e){//是否出現錯誤if (e.Error != null){MessageBox.Show(e.Error.ToString());return;}
//是否為使用者取消if (e.Cancelled){txt1.Text = "終止";txt2.Text = "Worked";}else{txt1.Text = "完畢";txt2.Text = "Worked";}}

//啟動private void btnStart_Click(object sender, RoutedEventArgs e){//是否正在執行一個非同步操作if (bw.IsBusy)return;
pro1.Maximum = 100;btnStart.IsEnabled = false;btnStop.IsEnabled = true;bw.RunWorkerAsync("hello world");
}
//停止private void btnStop_Click(object sender, RoutedEventArgs e){bw.CancelAsync();btnStart.IsEnabled = true;btnStop.IsEnabled = false;}
}}