Task
使用
Task以及Task.Factory都是在.Net 4引用的。Task跟Thread很類似,通過下面例子可以看到。
static public void ThreadMain() { Thread t1 = new Thread(TaskWorker); t1.Start(3); } static public void TaskMain() { Task t1 = new Task(TaskWorker, 3, TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning | TaskCreationOptions.AttachedToParent); Console.WriteLine(t1.Status); t1.Start(); t1.Wait(); // need to wait for finishing. } static public void TaskWorker(object state) { int nTime = (int)state; for (int i = 0; i < nTime; i++) { Thread.Sleep(100); Console.WriteLine(string.Format("current thread {0} sleep for {1} miniseconds .", Task.CurrentId, (i + 1) * 100)); } return; }
我們看到TaskWorker都是用於Task以及Thread,都是只能接受一個參數(Action<object>),不過task可以支持工作函數具有返回值(Func<TRessult>()或者Func<object, TResult>)。但是弱的類型輸入跟thread一樣。Task提供返回值是為了后面說到的task結構層次有用。
下面是調用一個具有返回值的工作函數
static public int TaskWorkerWithReturn(object state) { int nTime = (int)state; for (int i = 0; i < nTime; i++) { Thread.Sleep(100); Console.WriteLine(string.Format("current thread {0} sleep for {1} miniseconds .", Task.CurrentId, (i + 1) * 100)); } nTime++; return nTime; }
主調函數為:
Task<int> t2 = new Task<int>(TaskWorkerWithReturn, 3, TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning | TaskCreationOptions.AttachedToParent); t2.Start(); t2.Wait(); Console.WriteLine(t2.Result);不管從工作函數是否有返回值,task都需要在其運行過程中至少有一個前台線程在跑,否則會直接退出,根本原因是所有task都是后台線程。task的工作函數的輸入參數類型職能是object。
同步
對於沒有返回值的工作函數需要通過內核對象來同步主調線程(例如task內置的事件,使用wait來阻塞等待);
對於有返回值的工作函數可以通過訪問其Result函數來實現阻塞等待。
static public int TaskWorkerWithReturn(object state) { int nTime = (int)state; for (int i = 0; i < nTime; i++) { Thread.Sleep(100); Console.WriteLine(string.Format("current thread {0} sleep for {1} miniseconds .", Task.CurrentId, (i + 1) * 100)); } nTime++; return nTime; }
主調函數:
Task<int> t2 = new Task<int>(TaskWorkerWithReturn, 3, TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning | TaskCreationOptions.AttachedToParent); t2.Start(); Console.WriteLine("t2:" + t2.Result);
異步調用
作為新的一個特性在.net 4中引入,task能實現豐富的異步調用,使用成員函數ContinueWith來響應異步工作函數的完成,注意,不一定由之前完成異步函數的線程執行。
static public void TaskMain() { Task<int> t3 = new Task<int>(FirstTask, 1); t3.Start(); Task<int> t4 = t3.ContinueWith<int>(RecusiveTask); Task<int> t5 = t4.ContinueWith<int>(RecusiveTask); Task<int> t6 = t5.ContinueWith<int>(RecusiveTask).ContinueWith<int>(RecusiveTask); //Console.WriteLine(string.Format("final result: {0}", t6.Result)); } static public int FirstTask(object state) { int data = (int)state; for (int i = 0; i < data; i++) { Thread.Sleep(100); Console.WriteLine(string.Format("current thread {0} slept for {1} milisecond.", Task.CurrentId, (i + 1) * 100)); } data++; return data; } static public int RecusiveTask(Task<int> T) { int data = T.Result; for (int i = 0; i < data; i++) { Thread.Sleep(100); Console.WriteLine(string.Format("current thread {0} slept for {1} milisecond.", Task.CurrentId, (i + 1) * 100)); } data++; return data; }輸出結果為:
current thread 1 slept for 100 milisecond. current thread 2 slept for 100 milisecond. current thread 2 slept for 200 milisecond. current thread 3 slept for 100 milisecond. current thread 3 slept for 200 milisecond. current thread 3 slept for 300 milisecond. current thread 4 slept for 100 milisecond. current thread 4 slept for 200 milisecond. current thread 4 slept for 300 milisecond. current thread 4 slept for 400 milisecond. current thread 5 slept for 100 milisecond. current thread 5 slept for 200 milisecond. current thread 5 slept for 300 milisecond. current thread 5 slept for 400 milisecond. current thread 5 slept for 500 milisecond. final result: 6 請按任意鍵繼續. . .