雖然使用線程池ThreadPool讓我們使用多線程變得容易,但是因為是由系統來分配的,如果想對線程做精細的控制就不太容易了,比如某個線程結束后執行一個回調方法。恰好Task可以實現這樣的需求。這篇文章我從以下幾點對Task進行總結。
- 認識Task
- Task的用法
認識Task
Task類在命名空間System.Threading.Tasks下,通過Task的Factory返回TaskFactory類,以TaskFactory.StartNew(Action)方法可以創建一個新的異步線程,所創建的線程默認為后台線程,不會影響前台UI窗口的運行。
如果要取消線程,可以利用CancellationTakenSource對象。如果要在取消任務后執行一個回調方法,則可以使用Task的()方法。
Task的用法
利用Task對之前的例子進行重寫和擴展。代碼如下。
namespace ThreadDemo { class Program { static void Main(string[] args) { // 創建CancellationTokenSource對象用於取消Task CancellationTokenSource cancelTokenSource = new CancellationTokenSource(); Fish fish1 = new Fish() { Name = "小黃魚", Score = 1 }; Fish fish2 = new Fish() { Name = "大鯊魚", Score = 100 }; // 創建一個Task Task task1 = new Task(() => fish1.Move(cancelTokenSource.Token), cancelTokenSource.Token); task1.Start(); // Task1被取消后的回調方法(小黃魚被擊中后顯示積分) task1.ContinueWith(fish1.ShowScore); Task task2 = new Task(() => fish2.Move(cancelTokenSource.Token), cancelTokenSource.Token); task2.Start(); task2.ContinueWith(fish2.ShowScore); // 按任意鍵發射 Console.ReadKey(); // 武器工廠線程池 Gun gun = new Gun(); LaserGun laserGun = new LaserGun(); TaskFactory taskFactory = new TaskFactory(); Task[] tasks = new Task[] { taskFactory.StartNew(()=>gun.Fire()), taskFactory.StartNew(()=>laserGun.Fire()) }; // 執行武器開火 taskFactory.ContinueWhenAll(tasks, (Task) => { }); cancelTokenSource.Cancel(); Console.ReadKey(); } } /// <summary> /// 魚 /// </summary> public class Fish { public string Name { get; set; } public int Score { get; set; } public Fish() { } public void Move() { Console.WriteLine(string.Format("{0}在游來游去...", Name)); } /// <summary> /// 游動 /// </summary> /// <param name="cancelToken"></param> public void Move(CancellationToken cancelToken) { while (!cancelToken.IsCancellationRequested) { Console.WriteLine(string.Format("{0}在游來游去...", Name)); // 阻塞1秒 Thread.Sleep(1000); } } /// <summary> /// 中槍后顯示獎勵 /// </summary> /// <param name="task"></param> public void ShowScore(Task task) { Console.WriteLine(string.Format("{0}中彈了,你得到{1}分",Name,Score)); } } }
程序運行結果如下:
下一篇文章我將要總結關於多線程的安全的問題,歡迎大家繼續關注。