首页 > 代码库 > 多线程——Task

多线程——Task




背景:

                以前想用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获得对一个同步上下文任务调度起的引用。




多线程——Task