BackgroundWorker 在執行DoWork事件時該如何取消呢?
方法1 DoWork 執行一個(耗時)循環
方法2 DoWork執行一個(耗時)方法[注:方法沒有循環]
見代碼:
方法1中DoWork事件執行的是一個for循環(foreach,while.....)
取消操作很簡單,隻要在循環中判斷即可
#region
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Threading;
using System.Text.RegularExpressions;
namespace ConsoleBackgroundworker
{
class Program
{
static BackgroundWorker bw;
static void Main()
{
bw = new BackgroundWorker();
bw.WorkerReportsProgress = true;
bw.WorkerSupportsCancellation = true;
bw.DoWork += bw_DoWork;
bw.ProgressChanged += bw_ProgressChanged;
bw.RunWorkerCompleted += bw_RunWorkerCompleted;
bw.RunWorkerAsync("Hello to worker");
Console.WriteLine("Press /"C/" to cancel");
while (true)
{
//按C取消
if (Console.ReadKey(true).Key == ConsoleKey.C)
{
if (bw.IsBusy)
bw.CancelAsync(); //送出取消指令,但還未取消
else { break; }
}
}
//Console.ReadLine();
}
static void bw_DoWork(object sender, DoWorkEventArgs e)
{
Console.WriteLine(e.Argument);
for (int i = 0; i <= 100; i += 1)
{
//判斷是否取消操作
if (bw.CancellationPending)
{
e.Cancel = true; //這裡才真正取消
return;
}
//傳遞給ProgressChanged
bw.ReportProgress(i);
Thread.Sleep(100);
e.Result = i;
}
// 最終傳遞給RunWorkerCopmleted
}
static void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
Console.WriteLine("You cancelled!");
else if (e.Error != null)
Console.WriteLine("Worker exception: " + e.Error.ToString());
else
{
Console.WriteLine("Complete - " + e.Result); // 從 DoWork
}
}
static void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
Console.Write("{0,3}/b/b/b", e.ProgressPercentage);
}
}
}
#endregion
方法2中DoWork事件中執行的是一個比較耗時的方法時該怎麼辦了.方法中沒有循環無法判斷使用者是否執行了取消操作!
那麼這裡就要用到[異步程式設計模式],在執行一個比較耗時的方法時,代碼還能繼續向下運作.....!
BackgroundWorker bgworker = new BackgroundWorker();
gworker.WorkerSupportsCancellation = true; //是否支援異步取消 如果要取消操作必須設定true
bgworker.DoWork += new DoWorkEventHandler(this.bgworker_DoWork);
bgworker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.bgworker_RunWorkerCompleted);
private void begin_Click(object sender, EventArgs e)
{
//開始
if(!bgworker.IsBusy)
{
bgworker.RunWorkerAsync(); //開始操作
}
}
private void end_Click(object sender, EventArgs e)
{
//開始取消
if (bgworker.IsBusy) //是否在運作異步操作
{
bgworker.CancelAsync(); //(是)送出取消指令
}
}
private void bgworker_DoWork(object sender, DoWorkEventArgs e)
{
//Sql語句 查詢的資料很多
string sql = "select * from table";
//綁定委托要執行的方法
Del_DoWork work = new Del_DoWork(ReturnDataTable);
//開始異步執行(ReturnDataTable)方法
IAsyncResult ret = work.BeginInvoke(sql, null, null);
//(異步程式設計模式好久就是在執行一個很耗時的方法(ReturnDataTable)時,還能向下繼續運作代碼)
//接着運作下面的while循環,
//判斷異步操作是否完成
while (!ret.IsCompleted)
{
//沒完成
//判斷是否取消了backgroundworker異步操作
if (bgworker.CancellationPending)
{
//如何是 馬上取消backgroundwork操作(這個地方才是真正取消)
e.Cancel = true;
return;
}
}
e.Result = work.EndInvoke(ret); //傳回查詢結果 指派給e.Result
}
private delegate DataTable Del_DoWork(string sql); //建立一個委托
/// <summary>
/// 查詢資料庫表--------一個很耗時的方法
/// </summary>
/// <param name="sql"></param>
/// <returns></returns>
private DataTable ReturnDataTable(string sql)
{
DataTable table = new DataTable();
SqlConnection conn = new SqlConnection("Server............");
//.....................(省略)
return table;
}
private void bgworker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
MessageBox.Show("您取消了操作!");
}
else if (e.Error != null)
{
MessageBox.Show("出現錯誤!");
}
else
{
DataTable table = e.Result as DataTable;
if (table != null)
{
//得到資料,進行顯示操作
//dataGridView1.DataSource = table;
}
}
}