[C#.NET][TPL] Task 生命週期狀態
不論玩什麼技術,瞭解生命週期是很重要的一件事,TaskStatus 列舉 是平行運算函式庫的生命週期狀態,TaskStatus 列舉 的成員如下
初始化狀態:
- Created
- WaitingForActivation
- WaitingToRun
最終狀態:
- RanToCompletion
- Canceled
- Faulted
由下圖所示:
Created:
這很容易理解,建立任務但未開始執行(未調用Start)
private void DoWork1()
{
CancellationTokenSource cts = new CancellationTokenSource();
Task t = new Task(() =>
{
SpinWait.SpinUntil(() =>
{
return false;
}, 10000);
}, cts.Token);
var status = t.Status.ToString();
MessageBox.Show(status);
}
WaitingToRun:
已經排定任務,正要啟動,就算立即調用 Start 方法也不見得會立馬啟動,千萬要記住不管是平行運算還是傳統的執行緒,都不會立馬啟動。
private void DoWork2()
{
CancellationTokenSource cts = new CancellationTokenSource();
Task t = new Task(() =>
{
SpinWait.SpinUntil(() =>
{
return false;
}, 10000);
}, cts.Token);
t.Start();
var status = t.Status.ToString();
MessageBox.Show(status);
}
執行結果如下:
Running:
調用 Start 後,動點手腳才能看觀察任務已經在執行。
private void DoWork3()
{
CancellationTokenSource cts = new CancellationTokenSource();
Task t = new Task(() =>
{
SpinWait.SpinUntil(() =>
{
return false;
}, 10000);
}, cts.Token);
t.Start();
SpinWait.SpinUntil(() => false, 100);
var status = t.Status.ToString();
MessageBox.Show(status);
}
Canceled:
調用CancellationTokenSource.Cancel,在方法體內要調用ThrowIfCancellationRequested方法,這時就能看到狀態是Cancel
private void DoWork4()
{
CancellationTokenSource cts = new CancellationTokenSource();
Task t = new Task(() =>
{
SpinWait.SpinUntil(() =>
{
cts.Token.ThrowIfCancellationRequested();
return false;
}, 10000);
}, cts.Token);
t.Start();
SpinWait.SpinUntil(() => false, 100);
cts.Cancel();
SpinWait.SpinUntil(() => false, 100);
var status = t.Status.ToString();
MessageBox.Show(status);
}
執行結果如下:
RanToCompletion:
任務完成,在這裡我利用Task.ContinueWith方法來叫起另外一個任務,用來觀察任務完成。
private void DoWork5()
{
CancellationTokenSource cts = new CancellationTokenSource();
Task t = new Task(() =>
{
SpinWait.SpinUntil(() =>
{
cts.Token.ThrowIfCancellationRequested();
return false;
}, 10000);
}, cts.Token);
t.Start();
t.ContinueWith((t1) =>
{
var status = t.Status.ToString();
MessageBox.Show(status);
});
}
執行結果如下:
Faulted:
在這裡我仍是接續另一個子任務,用來觀察父任務的狀態,故意拋出一個例外,讓子任務接收。
private void DoWork6()
{
CancellationTokenSource cts = new CancellationTokenSource();
Task t = new Task(() =>
{
SpinWait.SpinUntil(() =>
{
cts.Token.ThrowIfCancellationRequested();
return false;
}, 1000);
throw new Exception("Demo");
}, cts.Token);
t.Start();
t.ContinueWith((t1) =>
{
try
{
t.Wait();
}
catch (AggregateException ex)
{
//TODO:補捉例外
foreach (var innerException in ex.InnerExceptions)
{
Console.WriteLine(innerException.ToString());
}
}
finally
{
var status = t.Status.ToString();
MessageBox.Show(status);
}
}, TaskContinuationOptions.OnlyOnFaulted);
}
執行結果如下:
以上簡單的程式碼就能測出任務狀態,但是,我試了好久無法測出 WaitingForActivation 狀態在什麼情況下會出現,若知道的人可以告訴我一下。
更多資料可參考
http://msdn.microsoft.com/en-us/library/ff963549.aspx
補充:
WaitingForActivation:
用Task.ContinueXXX 關鍵字的 Task,就能觀察到這個狀況。
我返回 t1 便能觀察到它的 TaskStatus
private void DoWork7()
{
CancellationTokenSource cts = new CancellationTokenSource();
var mainTask = new Task(() =>
{
SpinWait.SpinUntil(() =>
{
cts.Token.ThrowIfCancellationRequested();
return false;
}, 10000);
}, cts.Token);
var subTask = mainTask.ContinueWith((t1) =>
{
var status = mainTask.Status.ToString();
MessageBox.Show(status);
return t1;
});
mainTask.Start();
Thread.Sleep(100);
MessageBox.Show(string.Format("main task status:{0}\r\nsub task status:{1}", mainTask.Status, subTask.Status));
}
執行結果如下:
主任務完成後跳出下圖:
下圖是調用方法狀態改變的順序:
還缺一個 WaitingForChildrenToComplete 狀態不知如何觀察,知道的人可以跟我講一下喔。
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET