多線程系列(3)任務Task


  雖然使用線程池ThreadPool讓我們使用多線程變得容易,但是因為是由系統來分配的,如果想對線程做精細的控制就不太容易了,比如某個線程結束后執行一個回調方法。恰好Task可以實現這樣的需求。這篇文章我從以下幾點對Task進行總結。

  1. 認識Task
  2. 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));
        }
    }
}

 

 

程序運行結果如下:

下一篇文章我將要總結關於多線程的安全的問題,歡迎大家繼續關注。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM