多线程系列(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));

        }

    }

}

 

 

程序运行结果如下:

下一篇文章我将要总结关于多线程的安全的问题,欢迎大家继续关注。

你可能感兴趣的:(task)