Task類(任務),task類任務
任務表示應完成的某個單元的工作。這個單元的工作可以在單獨的線程中運行,也可以以同步方式啟動一個任務,這需要等待主調用線程。使用任務不僅可以獲得一個抽象層,還可以對底層線程進行很多控制。
1.啟動任務
要啟動任務,可以使用TaskFactory類或Task類的構造函數和Start()方法。Task類的構造函數在創建任務上提供的靈活性較大。
1).任務方法

![]()
static object taskMethodLock = new object();
static void TaskMethod(object title)
{
lock (taskMethodLock)
{
Console.WriteLine(title);
Console.WriteLine("Task id: {0}, thread: {1}",
Task.CurrentId == null ? "no task" : Task.CurrentId.ToString(),
Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("is pooled thread: {0}", Thread.CurrentThread.IsThreadPoolThread);
Console.WriteLine("is background thread: {0}", Thread.CurrentThread.IsBackground);
Console.WriteLine();
}
}
View Code
2).使用線程池的任務

![]()
static void TasksUsingThreadPool()
{
var tf = new TaskFactory();
Task t1 = tf.StartNew(TaskMethod, "using a task factory");
Task t2 = Task.Factory.StartNew(TaskMethod, "factory via a task");
var t3 = new Task(TaskMethod, "using a task constructor and Start");
t3.Start();
Task t4 = Task.Run(() => TaskMethod("using the Run method"));
}
View Code
執行結果:

3).同步任務
任務也可以同步運行,已相同的線程作為主調用線程。
注:主線程是一個調用前台線程,沒有任務ID,也不是線程池中的線程。

![]()
private static void RunSynchronousTask()
{
TaskMethod("just the main thread");
var t1 = new Task(TaskMethod, "run sync");
t1.RunSynchronously();
}
View Code
執行結果:

4).使用單獨線程的任務
如果任務的代碼應該長時間運行,就應該使用TaskCreationOptions.LogRunning告訴任務調度器創建一個新線程,而不是使用線程池中的線程。

![]()
private static void LongRunningTask()
{
var t1 = new Task(TaskMethod, "long running", TaskCreationOptions.LongRunning);
t1.Start();
}
View Code
執行結果:

2.Future——任務結果
任務結束時,它可以把一些有用的狀態信息寫到共享對象中。這個對象必須是線程安全的。另一個選項是使用返回某個結果的任務。這種任務也叫Future,因為它返回一個結果。

![]()
static Tuple<int, int> TaskWithResult(object division)
{
Tuple<int, int> div = (Tuple<int, int>)division;
int result = div.Item1 / div.Item2;
int reminder = div.Item1 % div.Item2;
Console.WriteLine("task creates a result...");
return Tuple.Create<int, int>(result, reminder);
}
View Code

![]()
static void ResultsFromTasks()
{
var t1 = new Task<Tuple<int, int>>(TaskWithResult, Tuple.Create<int, int>(8, 3));
t1.Start();
Console.WriteLine(t1.Result);
t1.Wait();
Console.WriteLine("result from task: {0} {1}", t1.Result.Item1, t1.Result.Item2);
}
View Code
執行結果:

3.連續任務
通過任務,可以指定在任務完成後,應開始運行另一個特定任務。
注:無論前一個任務是如何結束的,前面的連續任務總是在前一個任務結束時啟動。使用TaskContinuationOptions枚舉中的值,可以指定,連續任務只有在起始任務成功(或失敗)結束時啟動。一些可能的值是OnlyOnFaulted、NotOnFaulted、OnlyOnCanceled和OnlyOnRanToCompletion。

![]()
static void DoOnFirst()
{
Console.WriteLine("doing some task {0}", Task.CurrentId);
Thread.Sleep(3000);
}
static void DoOnSecond(Task t)
{
Console.WriteLine("task {0} finished", t.Id);
Console.WriteLine("this task id {0}", Task.CurrentId);
Console.WriteLine("do some cleanup");
Thread.Sleep(3000);
}
static void DoOnError(Task t)
{
Console.WriteLine("task {0} had an error!", t.Id);
Console.WriteLine("my id {0}", Task.CurrentId);
Console.WriteLine("do some cleanup");
}
View Code

![]()
static void ContinuationTask()
{
Task t1 = new Task(DoOnFirst);
Task t2 = t1.ContinueWith(DoOnSecond);
Task t3 = t1.ContinueWith(DoOnSecond);
Task t4 = t2.ContinueWith(DoOnSecond);
Task t5 = t1.ContinueWith(DoOnError, TaskContinuationOptions.OnlyOnFaulted);
t1.Start();
Thread.Sleep(5000);
}
View Code
執行結果:

4.任務層次結構
利用任務連續性,可以在一個任務結束後啟動另一個任務。任務也可以構成一個層次結構。一個任務啟動一個新任務時,就啟動了一個父/子層次結構。
如果父任務在子任務之前結束,父任務的狀態就顯示為:WaitingForChildrenToComplete。所有的子任務也結束時,父任務的狀態就變成RanToCompletion。

![]()
static void ParentAndChild()
{
var parent = new Task(ParentTask);
parent.Start();
Thread.Sleep(2000);
Console.WriteLine(parent.Status);
Thread.Sleep(4000);
Console.WriteLine(parent.Status);
}
static void ParentTask()
{
Console.WriteLine("task id {0}", Task.CurrentId);
var child = new Task(ChildTask); // , TaskCreationOptions.DetachedFromParent);
child.Start();
Thread.Sleep(1000);
Console.WriteLine("parent started child");
// Thread.Sleep(3000);
}
static void ChildTask()
{
// Console.WriteLine("task id {0}, parent: {1}", Task.Current.Id, Task.Current.Parent.Id);
Console.WriteLine("child");
Thread.Sleep(5000);
Console.WriteLine("child finished");
}
View Code
執行結果:
