PLINQ 取消執行
PLINQ通常都是使用在大量資料查詢的時候,所以會發生一個查詢花費很長的時間。 PLINQ 有提供WithCancellation方法,程式師可以強制將查詢取消。
將cancellation tokens傳入WithCancellation()方法,然後從外部執行取消的動作,就可以取消。 取消後會拋出OperationCanceledException,所以要記得catch OperationCanceledException做後續處理。
範例如下:
public void Run()
{
int[] source = Enumerable.Range(1, 1000000).ToArray();
// 使用CancellationTokenSource 產生Token傳入WithCancellation
using (CancellationTokenSource cts = new CancellationTokenSource())
{
// 這在邊先開一個非同步任務做取消的觸發動作
Task.Factory.StartNew(
() => this.UserClicksTheCancelButton(cts)
);
double[] results = null;
try
{
results = (from num in source.AsParallel()
.WithCancellation(cts.Token) // 傳入Token
where num % 3 == 0
select Function(num, cts.Token)).ToArray();
}
catch (OperationCanceledException e) // 取消後會拋出 OperationCanceledException
{
Console.WriteLine(e.Message);
Console.WriteLine("已取消執行");
}
if (results != null)
{
foreach (var item in results)
{
Console.WriteLine(item);
}
}
}
}
private double Function(int num, CancellationToken cts)
{
for (int i = 0; i < 50; i++)
{
// 假設執行很長時間
Thread.Sleep(1000);
Console.WriteLine(i);
// 檢查是否取消了
cts.ThrowIfCancellationRequested();
}
return Math.Sqrt(num);
}
private void UserClicksTheCancelButton(CancellationTokenSource cts)
{
Console.WriteLine("Press 'c' to cancel");
if (Console.ReadKey().KeyChar == 'c')
{
// 執行取消動作
cts.Cancel();
}
}
當取消查詢的時候,已經完成的任務就完成了,沒辦法退回,而已經開始執行的任務會被允許完成。 最後尚未排入的任務,則不會執行。
一天一分享,身體好健康。
該追究的不是過去的原因,而是現在的目的。