多线程——Task

来源:互联网 发布:单片机外部中断程序 编辑:程序博客网 时间:2024/06/05 10:03




背景:

                以前想用Semaphore来处理并发访问资源的问题,后来把方案拿给前辈们看的时候,他们说这样也行,但是最好用Task处理,比较简单。所以,顺便学习了下Task.



使用task类创建并执行简单任务







等待任务的完成并获取返回值







使用ContinueWith方法在任务完成时启动一个新任务






创建父子任务和任务工厂的使用



<span style="font-size:12px;">namespace 创建父子任务和任务工厂的使用{    class Program    {        //通过task类创建的任务是顶级任务,可以通过使用TaskCreationOptions .AttachedToParent 标识把这些任务与创建他的任务相关联        //所有子任务完成以后父任务才会结束操作        //        static void Main(string[] args)        {          #region 创建父子任务Demo              //Task<string[]> parent = new Task<string[]>(state => {              //      Console.WriteLine(state);              //      string[] result = new string[2];              //      //创建并启动子任务              //      new Task(() => { result[0] = "任务1。。。"; },TaskCreationOptions .AttachedToParent ).Start ();              //      new Task(() => { result [1]="任务2。。。";},TaskCreationOptions .AttachedToParent ).Start ();              //      return result ;              //  },"这里是父任务,并在处理过程中创建多个子任务,所有子任务完成以后才会执行。");              //  //任务处理完成后执行的操作              //  parent .ContinueWith (t=>{              //      Array.ForEach(t.Result, r => Console.WriteLine(r));              //  });              //  //启动父任务              //  parent .Start ();              //  Console .ReadKey ();     #endregion                    #region 任务工厂的使用            Task parent=new Task(()=>{                CancellationTokenSource cts =  new CancellationTokenSource();//为什么不包含一个参数的构造函数??????                               //创建任务工厂                     TaskFactory tf = new TaskFactory(cts.Token, TaskCreationOptions.AttachedToParent, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);            //添加一组具有相同状态的子任务            Task[] task=new Task[]{                            tf.StartNew (()=>{Console.WriteLine("我是任务工厂里的第一个任务");}),                tf.StartNew (()=>{Console .WriteLine("我是任务工厂里的第二个任务");}),                tf.StartNew (()=>{Console .WriteLine("我是任务工厂里的第三个任务");})                        };                                   });             parent .Start();             Console.ReadKey();            #endregion        }    }}</span>


任务内部的实现和调度


      任务内部有一组构成任务状态的属性,表示任务的唯一ID,表示任务的执行状态(TaskStatus),任务创建时提供的回调函数的引用和传递给回调函数的数据对象AsyncState,对任务创建时的任务调度对象(TaskScheduler)的引用,对父任务的引用以及对执行上下文的引用和ManualResetEventSlim对象的引用。


       Task和Task<TResult>类都实现了标准的释放资源的接口,允许在任务完成处理的时候使用Dispose方法释放资源(关闭ManualResetEventSlim对象实例)。可以使用Task类的CurrentID属性获得正在执行的任务的ID,如果没有任务在执行CurrentID返回的值为null,currentID是一个int,可空类型的属性。任务执行的生命周期通过TaskStatus类似的一个值来表示,TaskStatus所包含的值为taskstatus


   

namespace 任务内部的实现和调度{    class Program    {       static  void TestDemo()        {            //获得同步上下文任务调度器            TaskScheduler m_syncContextTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();//表示一个处理将任务排队到线程中的低级工作对象            //创建任务,并采用默认任务调度(线程池任务调度器)执行任务            Task<int> task = new Task<int>(() =>            {                //执行复杂的计算任务                Thread.Sleep(2000);//当前线程暂停2000                int sum = 0;                for (int i = 0; i < 100; i++)                {                    sum += i;                }                return sum;            });            var cts = new CancellationTokenSource();            //任务完成时启动一个后续任务,并采用同步上下文任务调度器调度任务更新UI组件            task.ContinueWith(t => { Console.WriteLine("采用SynchronizationContextTaskScheduler任务调度器更新UI。\r\n计算结果是:" + task.Result.ToString()); }, cts.Token, TaskContinuationOptions.AttachedToParent, m_syncContextTaskScheduler);            task.Start();        }               static void Main(string[] args)        {            TestDemo();        }    }    #region TaskStatus所包含的值:        //    public enum TaskStatus    //{    //    Created = 0,    //    WaitingForActivation = 1,    //    WaitingToRun = 2,    //    Running = 3,    //    WaitingForChildrenToComplete = 4,    //    RanToCompletion = 5,    //    Canceled = 6,    //    Faulted = 7    //}     #endregion}


    我们可以通过Task类的Exception属性获得任务在执行过程中的所有异常,Exception是一个AggregateException类型的属性。Task类提供了IsCanceled、IsCompleted、IsFaulted属性来获得任务的完成状态。通过ContinueWith、ContinueWhenAll、ContinueWhenAny和FromAsync创建的后续任务都处于WaitingForActivation状态,这个状态的任务会在父任务完成后自动执行。

 

       在任务内部由TaskScheduler类调度任务的执行,该类是一个抽象类,FCL中从他派生了两个派生类:ThreadPoolTaskScheduler线程池任务调度器和SynchronizationContextTaskScheduler同步上下文任务调度器。所有任务默认都是采用ThreadPoolTaskScheduler调度任务,他是采用线程池来执行任务,可以通过TaskScheduler类的静态属性Default获得对默认任务调度器的引用。SynchronizationContextTaskScheduler任务调度器能够用在Windowform、WPF等应用程序,他的任务调度是采用的GUI线程,所以他能同步更新UI组件,可以通过TaskScheduler类的静态方法FromCurrentSynchronizationContext获得对一个同步上下文任务调度起的引用。




0 0