在之前我寫過一篇關於用 Task 類別來撰寫非同步化作業(使用 Task 自行控制非同步任務作業),來利用多CPU、多核心處理器的優勢,這樣可以避免某些邏輯需要較長的時間去執行,而造成主界面程式停頓卡卡,讓使用者誤以為當機、或程式有問題,所以透過.Net 的 Task 任務,可以讓系統自行的調度限制可以用的執行緒(Thread)。
既然有了 Task 任務類別的支援,可以讓我們輕易的撰寫多工、非同步作業的程式,讓長時間執行的程式透過另外一個執行緒(Thread)在背後執行,例如我常幫工廠或企業寫物料需求計算(MRP、MPS計算)、業績獎金計算、APS先進排程規劃,這些都是需要執行讀取大量的系統資料來進行運算,這就可以充分利用 Thrad、Task的技術再背後另外一個執行緒去執行,使用者,在前端主畫面還可以繼續執行其他作業,而不用只能等待程式執行完畢。
不過我們也常常遇到常時間執行的程式,我們可以提供一個按鈕讓使用者去選擇【取消】背後執行的任務,那麼這篇技術文章我就是想講解,如何在.Net 平台取消非同步化作業的任務 ,.net 平台裡有個類別專門跟 Task 、Task<TResult> 類別搭配使用,使得完成取消非同步任務作業的執行,這個類別就是 CancellationTokenSource 類別。
我在這邊一樣透過 Step By Step 來建立一個範例程式,來說明整個程式的撰寫技巧…
1.這邊我簡單為了好示範,我建立一個 Windows Form 視窗專案,命名為 CancellationTokenSource_Demo,如下圖:

2.在 Form1 表單,我設計了一下畫面

在Form1表單,我為了示範,所以放置了2個 Label (分別顯示 輸入一個正整數、運算結果顯示),2個 Button 按鈕(分別為 進行運算、取消非同步任務),還有一個 ProgressBar (作用於非同步任務執行時,可以顯示進度條狀態)。
3.在 Form1.cs 的後端程式,是最重要的,我把程式標註註解,這樣大家就可以容易理解了。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
/// <summary>
/// 宣告一個 用於支援取消非同步任務的變數
/// </summary>
private CancellationTokenSource cts = null;
private void btnCalc_Click(object sender, EventArgs e)
{
//取得的正整數
int currNum = 0;
if (!int.TryParse(txtInputInt.Text, out currNum))
{
MessageBox.Show("必須輸入一個正整數數字!");
return;
}
//清楚執行結果
txtFinalResult.Clear();
btnStartCalc.Enabled = false; //將【進行運算】按鈕啟用狀態取消
btnCancel.Enabled = true; //將【取消非同步任務】按鈕啟用狀態啟用
//用於顯示報告進度條的變數
IProgress<int> progRpt = new Progress<int>((p) =>
{
this.progressBar1.Value = p;
});
//如果 CancellationTokenSource 物件變數不是為 null , 比較進行釋放(務必)
if (cts != null)
{
cts.Dispose();
}
//實體化 CancellationTokenSource 物件
cts = new CancellationTokenSource();
//宣告一個任務變數
Task<string> task = new Task<string>(() =>
{
BigInteger bint = new BigInteger(1d);
double totalProgress = (double)currNum;
//如果CancellationTokenSource 物件的 IsCancellationRequested 值為 true ,代表使用者已經將非同步任務進行取消
for (int i = 1; i <= currNum && !cts.IsCancellationRequested; i++)
{
bint *= i; //相乘
double progressVal = Convert.ToDouble(i) / totalProgress * 100d;
//顯示非同步任務執行的進度表
progRpt.Report(Convert.ToInt32(progressVal));
}
//傳回執行結果
return bint.ToString();
}, cts.Token, TaskCreationOptions.LongRunning);
//開始執行非同步任務
task.Start();
//等待任務操作完成,等待1秒
while (!task.Wait(1000))
{
Application.DoEvents();
}
//顯示運算結果
txtFinalResult.Text = task.Result;
btnStartCalc.Enabled = true;
btnCancel.Enabled = false;
}
private void btnCancel_Click(object sender, EventArgs e)
{
//使用者執行取消非同步任務
if (cts != null)
{
cts.Cancel();
}
}
}




4.經過步驟3核心程式碼後,就可以編譯執行,執行結果畫面如下:
4-1.
執行運算中…

4-2.
中途,我執行【取消非同步任務】按鈕

完成上述這樣的示範,就可以撰寫讓使用者中途取消任務的執行。
參考文章
C#多工作業與平行處理技術講解
1.透過 Thread 類別撰寫多執行緒多工作業。
2.透過 Delegate 委託支援的方法,撰寫非同步任務。
3-1.透過 Parallel 類別操控多任務平行作業(一)。
3-2. 透過 Parallel 類別操控多任務平行作業(二)。
4.使用 Task 自行控制非同步任務作業。
5.在非同步作業時,如何取消非同步任務。
6.多執行緒多任務存取相同變數,但卻各自隔離保留各自任務的值。
7.非同步存取變數的問題。
8.非同步資源鎖定解決方式。
網智數位-軟體開發(軟件開發)
針對各特殊產業都可以量身定做符合貴公司的需求,別人無法克服的就是我們的挑戰
業務合作、軟體委外開發
業務窗口:allen@netqna.com
聯繫電話:0920-883-870
公司電話:02-55991310
公司地址(業務營運處):台北市中山區錦州街 25 號 5 樓
skype: netqna
line:netqna
微信:netqna
黃先生 Allen
既然有了 Task 任務類別的支援,可以讓我們輕易的撰寫多工、非同步作業的程式,讓長時間執行的程式透過另外一個執行緒(Thread)在背後執行,例如我常幫工廠或企業寫物料需求計算(MRP、MPS計算)、業績獎金計算、APS先進排程規劃,這些都是需要執行讀取大量的系統資料來進行運算,這就可以充分利用 Thrad、Task的技術再背後另外一個執行緒去執行,使用者,在前端主畫面還可以繼續執行其他作業,而不用只能等待程式執行完畢。
不過我們也常常遇到常時間執行的程式,我們可以提供一個按鈕讓使用者去選擇【取消】背後執行的任務,那麼這篇技術文章我就是想講解,如何在.Net 平台取消非同步化作業的任務 ,.net 平台裡有個類別專門跟 Task 、Task<TResult> 類別搭配使用,使得完成取消非同步任務作業的執行,這個類別就是 CancellationTokenSource 類別。
我在這邊一樣透過 Step By Step 來建立一個範例程式,來說明整個程式的撰寫技巧…
1.這邊我簡單為了好示範,我建立一個 Windows Form 視窗專案,命名為 CancellationTokenSource_Demo,如下圖:
2.在 Form1 表單,我設計了一下畫面
在Form1表單,我為了示範,所以放置了2個 Label (分別顯示 輸入一個正整數、運算結果顯示),2個 Button 按鈕(分別為 進行運算、取消非同步任務),還有一個 ProgressBar (作用於非同步任務執行時,可以顯示進度條狀態)。
3.在 Form1.cs 的後端程式,是最重要的,我把程式標註註解,這樣大家就可以容易理解了。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
/// <summary>
/// 宣告一個 用於支援取消非同步任務的變數
/// </summary>
private CancellationTokenSource cts = null;
private void btnCalc_Click(object sender, EventArgs e)
{
//取得的正整數
int currNum = 0;
if (!int.TryParse(txtInputInt.Text, out currNum))
{
MessageBox.Show("必須輸入一個正整數數字!");
return;
}
//清楚執行結果
txtFinalResult.Clear();
btnStartCalc.Enabled = false; //將【進行運算】按鈕啟用狀態取消
btnCancel.Enabled = true; //將【取消非同步任務】按鈕啟用狀態啟用
//用於顯示報告進度條的變數
IProgress<int> progRpt = new Progress<int>((p) =>
{
this.progressBar1.Value = p;
});
//如果 CancellationTokenSource 物件變數不是為 null , 比較進行釋放(務必)
if (cts != null)
{
cts.Dispose();
}
//實體化 CancellationTokenSource 物件
cts = new CancellationTokenSource();
//宣告一個任務變數
Task<string> task = new Task<string>(() =>
{
BigInteger bint = new BigInteger(1d);
double totalProgress = (double)currNum;
//如果CancellationTokenSource 物件的 IsCancellationRequested 值為 true ,代表使用者已經將非同步任務進行取消
for (int i = 1; i <= currNum && !cts.IsCancellationRequested; i++)
{
bint *= i; //相乘
double progressVal = Convert.ToDouble(i) / totalProgress * 100d;
//顯示非同步任務執行的進度表
progRpt.Report(Convert.ToInt32(progressVal));
}
//傳回執行結果
return bint.ToString();
}, cts.Token, TaskCreationOptions.LongRunning);
//開始執行非同步任務
task.Start();
//等待任務操作完成,等待1秒
while (!task.Wait(1000))
{
Application.DoEvents();
}
//顯示運算結果
txtFinalResult.Text = task.Result;
btnStartCalc.Enabled = true;
btnCancel.Enabled = false;
}
private void btnCancel_Click(object sender, EventArgs e)
{
//使用者執行取消非同步任務
if (cts != null)
{
cts.Cancel();
}
}
}
4.經過步驟3核心程式碼後,就可以編譯執行,執行結果畫面如下:
4-1.
執行運算中…
4-2.
中途,我執行【取消非同步任務】按鈕
完成上述這樣的示範,就可以撰寫讓使用者中途取消任務的執行。
參考文章
C#多工作業與平行處理技術講解
1.透過 Thread 類別撰寫多執行緒多工作業。
2.透過 Delegate 委託支援的方法,撰寫非同步任務。
3-1.透過 Parallel 類別操控多任務平行作業(一)。
3-2. 透過 Parallel 類別操控多任務平行作業(二)。
4.使用 Task 自行控制非同步任務作業。
5.在非同步作業時,如何取消非同步任務。
6.多執行緒多任務存取相同變數,但卻各自隔離保留各自任務的值。
7.非同步存取變數的問題。
8.非同步資源鎖定解決方式。
網智數位-軟體開發(軟件開發)
針對各特殊產業都可以量身定做符合貴公司的需求,別人無法克服的就是我們的挑戰
業務合作、軟體委外開發
業務窗口:allen@netqna.com
聯繫電話:0920-883-870
公司電話:02-55991310
公司地址(業務營運處):台北市中山區錦州街 25 號 5 樓
skype: netqna
line:netqna
微信:netqna
黃先生 Allen