.NET 4 中 包含了新名稱空間System.Threading.Task。它包含的類抽象出了線程的功能。使用Task類創建的任務是后台線程,所以在前台線程全部終止的時候,如果任務還沒有全部執行萬,就會被被動終止。
啟動任務
怎樣啟動一個任務?代碼中我們首先要添加using System.Threading.Tasks;引用。我們可以使用TaskFactory類或Task類的構造函數和Start()方法。在啟動任務時,會創建Task類的一個實例。首先我們看一段代碼
using System; using System.Text; using System.Threading.Tasks; using System.Threading; namespace ConsoleTask { class Program { static void Main(string[] args) { //使用TaskFactory創建一個任務
TaskFactory tf = new TaskFactory(); Task t1 = tf.StartNew(NewTask); //使用Task類de Factory創建一個任務
Task t2 = Task.Factory.StartNew(NewTask); /////////////////////////////////////// Task t3 = new Task(NewTask); t3.Start(); Task t4 = new Task(NewTask, TaskCreationOptions.PreferFairness); t4.Start(); Thread.Sleep(1000);//因為任務是后台線程,所以我們這里阻塞主線程一秒鍾來等待任務全部執行完成
} static void NewTask() { Console.WriteLine("開始一個任務"); Console.WriteLine("Task id:{0}",Task.CurrentId); Console.WriteLine("任務執行完成"); } } }
運行結果:
在上面代碼中。我們可以看到啟動新任務的不同方式:
1、 第一種使用實例化的TaskFactory類,把NewTask()方法傳遞給StartNew()方法,任務就會立即啟動。
2、 第二種方式是使用Task類的構造函數,實例化任務時,任務不會立即啟動,此時任務的狀態為Created。然后調用Task類的Start()方法來啟動任務,還可以調用RunSynchronously()方法來啟動任務。
默認情況下,任務是異步運行的。。。
使用Task類的構造函數和TaskFactory類的StartNew()方法時,都可以傳遞TaskCreationOptions枚舉中的值。
成員名稱 |
說明 |
None |
指定應使用默認行為。 |
PreferFairness |
提示 TaskScheduler 以一種盡可能公平的方式安排任務,這意味着較早安排的任務將更可能較早運行,而較晚安排運行的任務將更可能較晚運行。 |
LongRunning |
指定某個任務將是運行時間長、粗粒度的操作。 它會向 TaskScheduler 提示,過度訂閱可能是合理的。 |
AttachedToParent |
指定將任務附加到任務層次結構中的某個父級。 |
注:摘錄至MSDN:http://technet.microsoft.com/zh-CN/library/system.threading.tasks.taskcreationoptions
例如:如果任務使用子任務創建了其它任務,子任務就優先於其它任務。當然它們不會排在線程池的最后。如果這些任務應以公平的方式與所有其它任務一起處理,就設置選項為PerferFainress,如下所示
Task t4 = new Task(NewTask,TaskCreationOptions.PreferFairness); t4.Start();
創建連續的任務
通過創建任務,我們可以指定在一個任務完成過后,開始運行另外一個指定的任務。任務處理程序不帶參數或者帶一個Object類型的參數。連續處理程序有一個Task類型的參數,可以訪問起始任務的相關信息。
using System; using System.Threading.Tasks; using System.Threading; namespace ConsoleContinueTask { class Program { static void Main(string[] args) { Task t1 = new Task(FirstTask); Task t2 = t1.ContinueWith(SecondTask); t1.Start(); Thread.Sleep(7000); } static void FirstTask() { Console.WriteLine("第一個任務開始:TaskID:{0}",Task.CurrentId); Thread.Sleep(3000); } static void SecondTask(Task task) { Console.WriteLine("任務{0}完成",task.Id); Console.WriteLine("第二個任務開始:TaskID:{0}",Task.CurrentId); Console.WriteLine("清理工作......"); Thread.Sleep(3000); } } }
運行結果:
連續的任務通過在任務上調用ContinueWith()方法來定義。t1.ContinueWith(SecondTask)方法表示,調用SecondTask()方法的新任務應該在t1任務完成后立即啟動過,在第一個任務結束時,還可以啟動多個任務。無論前一個任務是如何結束的,前面的連續任務總是在前面一個任務結束時啟動,使用TaskContinueOptions枚舉中的值可以指定連續任務只有在起始任務成功或者失敗時啟動,TaskContinueOptions的枚舉值有
成員名稱 |
說明 |
None |
Default = "Continue on any, no task options, run asynchronously" 指定應使用默認行為。 默認情況下,完成前面的任務之后將安排運行延續任務,而不考慮前面任務的最終 TaskStatus。 |
PreferFairness |
提示 TaskScheduler 以一種盡可能公平的方式安排任務,這意味着較早安排的任務將更可能較早運行,而較晚安排運行的任務將更可能較晚運行。 |
LongRunning |
指定某個任務將是運行時間長、粗粒度的操作。 它會向 TaskScheduler 提示,過度訂閱可能是合理的。 |
AttachedToParent |
指定將任務附加到任務層次結構中的某個父級。 |
NotOnRanToCompletion |
指定不應在延續任務前面的任務已完成運行的情況下安排延續任務。 此選項對多任務延續無效。 |
NotOnFaulted |
指定不應在延續任務前面的任務引發了未處理異常的情況下安排延續任務。 此選項對多任務延續無效。 |
NotOnCanceled |
指定不應在延續任務前面的任務已取消的情況下安排延續任務。 此選項對多任務延續無效。 |
OnlyOnRanToCompletion |
指定只應在延續任務前面的任務已完成運行的情況下才安排延續任務。 此選項對多任務延續無效。 |
OnlyOnFaulted |
指定只應在延續任務前面的任務引發了未處理異常的情況下才安排延續任務。 此選項對多任務延續無效。 |
OnlyOnCanceled |
指定只應在延續任務前面的任務已取消的情況下才安排延續任務。 此選項對多任務延續無效。 |
ExecuteSynchronously |
指定應同步執行延續任務。 指定此選項后,延續任務將在導致前面的任務轉換為其最終狀態的相同線程上運行。 如果在創建延續任務時已經完成前面的任務,則延續任務將在創建此延續任務的線程上運行。 只應同步執行運行時間非常短的延續任務。 |
摘錄至MSDN:http://technet.microsoft.com/zh-CN/library/system.threading.tasks.taskcontinuationoptions
任務的層次結構
利用任務的連續性,就可以在一個任務結束后啟動另外一個任務。一個任務啟動一個新任務時,就啟動了一個父/子層次結構,如下所示:
using System; using System.Threading.Tasks; using System.Threading; namespace ConsoleLayer { class Program { static void Main(string[] args) { Task parent = new Task(ParentTask); parent.Start(); Thread.Sleep(1000); Console.WriteLine("父任務的狀態:{0}",parent.Status); Thread.Sleep(4000); Console.WriteLine("父任務的狀態:{0}",parent.Status); } public static void ParentTask() { Console.WriteLine("父任務{0}正在運行......",Task.CurrentId); Task child = new Task(ChildTask); child.Start(); Console.WriteLine("父任務啟動了子任務"); Thread.Sleep(1000); } static void ChildTask() { Console.WriteLine("子任務{0}正在運行......",Task.CurrentId); Thread.Sleep(3000); Console.WriteLine("子任務執行完成。"); } } }
運行結果:
如果父任務在子任務之前結束,父任務的狀態就會顯示為WatingForChildrenToComplete。子任務的任務完成后,父任務的狀態就是RanToCompletion。