zoukankan      html  css  js  c++  java
  • Clr Via C#读书笔记---计算限制的异步操作

    线程池基础

          1,线程的创建和销毁是一个昂贵的操作,线程调度以及上下文切换耗费时间和内存资源。

          2,线程池是一个线程集合,供应你的用程序使用。

          3,每个CLR有一个自己的线程池,线程池由CLR控制的所有的AppDomain共享。

          4,CLR初始化的时候,线程池没有线程的。

          5,线程池维护一个操作请求队列。当应用程序想要执行一个一步操作的时候,就调用某个方法。将记录项(empty)追加到线程池队列中,然后线程池代码从队列中提取这个记录项,然后将记录项派遣(dispatch)给一个线程池的线程。当线程池线程完成任务后,不会被销毁。该线程会继续返回到线程池中,进入空闲状态,等待另一个请求。

         6,多个应用程序向线程池发出多个请求的时候,只会尝试用一个线程来服务,当超过了线程池线程处理速度的时候,会创建额外的线程。

         7,当线程池线程空闲一段时间之后,会自己醒来终止自己释放资源

         8,线程池分为工作线程(worker)或者I/O线程,工作线程用于操作异步计算限制操作,I/O线程用于通知代码一个异步I/O限制操作已完成。异步编程模型:(Asychronous Programming Model   APM)

    执行简单的计算限制操作

          计算限制操作:指需要长时间的计算的线程

          1,要将一个异步,计算限制的操作放到线程池的队列中(向线程池添加一个“工作项”),调用ThreadPool类的几个方法:

          static Boolean QueueUserWorkItem(WaitCallback callBack)
          static Boolean QueueUserWorkItem(WaitCallback callBack,Object state)

          2,线程池以异步调用一个方法

              using System;

              using System.Threading;

              public static class Program{

                   public static void Main(){
                    Console.WriteLine("Main thread:queing an asynchronous operation");

                    TreadPool.QueueUserWorkItem(ComputeBoundOp,5);

                    Console.WriteLine("Main thread:Doing other work here....");

                    Thread.Sleep(10000);

                    Console.WriteLine("按任意键继续")
              }

             private static void ComputeBoundOp(Object state){

                  Consol.WriteLine("In ComputeBoundOp:state={0}",state);

                   Thread.Sleep(1000);//模拟其他工作1秒钟

                    

               }

          }

    执行上下文

         多任务系统往往需要同时执行多道作业。作业数往往大于机器的CPU数,然而一颗CPU同时只能执行一项任务,为了让用户感觉这些任务正在同时进行,操作系统的设计者巧妙地利用了时间片轮转的方式,CPU给每个任务都服务一定的时间,然后把当前任务的状态保存下来,在加载下一任务的状态后,继续服务下一任务。任务的状态保存及再加载,这段过程就叫做上下文切换。

        1,每个线程都关联了一个执行上下文的数据结构

        2,执行上下文包括:安全设置(压缩栈,Thread的Principal属性和windows身份),宿主设置(System.Treading.HostExcepitonContextManager)以及逻辑调用上下文数据(System.Runtime.Remoting.Messaging.CallContext的LogicalSetData和LogicalGetData)

        3,线程执行代码有时候会受到执行上下文设置(安全设置居多)的影响

        4,线程执行上下文可流动性。一个线程(初始线程)使用另一个线程(辅助线程)执行任务时,前者上下文应该流向(复制)辅助线程(耗性能).

        5,阻止上下文的流动,可提高应用程序性能。

    协作式取消

          .net Framework提供了一套协作式取消模式,支持显示取消长时间运行的计算限制操作。

          System.Thread.CancellationTokenSource对象:      

                public class CancellationTokenSource : IDisposable
                {
                       //构造函数
                        public CancellationTokenSource();
                       //获取是否已请求取消此

                        System.Threading.CancellationTokenSource
                        public bool IsCancellationRequested { get; }
                        //获取与此 System.Threading.CancellationTokenSource 关联的                                                                       System.Threading.CancellationToken
                        public CancellationToken Token;
                        //传达取消请求。
                        public void Cancel();
                        //传达对取消的请求,并指定是否应处理其余回调和可取消操作。
                        public void Cancel(bool throwOnFirstException);
                 }

              这个对象包含了管理取消有关的所有状态。构造好一个CancellationTokenSource(引               用类型)之后,可以从它的Token属性获得一个或多个CancellationToken(值类型)实                 例,并传给你的操作,使那些操作可以取消。以下是CancellationToken值类型最有用               的一些成员:

               public struct CancellationToken //一个值类型

                {
                   //获取此标记是否能处于已取消状态,IsCancellationRequested 由非通过Task来调用(invoke)的一个操作调用(call)
                   public bool IsCancellationRequested { get; }
                     //如果已请求取消此标记,则引发 System.OperationCanceledException,由通    过Task来调用的操作调用
                    public void ThrowIfCancellationRequested();
                   //获取在取消标记时处于有信号状态的 System.Threading.WaitHandle,取消时,                WaitHandle会收到信号
                    public WaitHandle WaitHandle { get; }
                  //返回空 CancellationToken 值。
                    public static CancellationToken None
                 //注册一个将在取消此 System.Threading.CancellationToken 时调用的委托。省略了简单重载版本
                    public CancellationTokenRegistration Register(Action<object> callback,                object state, bool useSynchronizationContext);

                 //省略了GetHashCode、Equals成员
              }

    CancellationToken实例是一个轻量级的值类型,它包含单个私有字段:对它的CancellationTokenSource对象的一个引用。在一个计算限制操作的循环中,可以定时调用CancellationToken的IsCancellationRequested属性,了解循环是否应该提前终止,进而终止计算限制的操作。当然,提前终止的好处在于,CPU不再需要把时间浪费在你对其结果已经不感兴趣的一个操作上。

    任务

         ThreadPool的QueueUserWorkItem 存在限制,没有一个内建机制让你知道什么时候完成,也没有一个机制在操作完成返回一个值。

         创建任务:

         System.Threading.Tasks创建一个任务

         创建Task任务调用的构造器,传递一个Action或者Action<Object>委托

         取消任务:    

         用一个CancellationTokenSource取消一个Task。

         一个任务完成时自动启动另一个新任务:

        调用ContinuWith()使得一个Task完成时调用新的任务-------- wait方法会导致线程堵塞导致消耗性能

        创建子任务:

           Task<Int32[]> parent=new Task<Int32[]>(()=>{
                 var results=new Int32[3];

                  new Task(()=>results[0])=Sum(10000),TaskCreationOptions.AttacjedToParent).Start();

                  new Task(()=>results[0])=Sum(20000),TaskCreationOptions.AttacjedToParent).Start();

                  new Task(()=>results[0])=Sum(30000),TaskCreationOptions.AttacjedToParent).Start();

                 return results;
           });

            //父任务及其子任务运行完成后,用一个延续任务显示结果

            var cwt=parent.ContinueWith(parentTask=>Array.Foreach(parentTask.Result,console.Writelin));

         任务内部揭秘:

         1,每个Task对象包含一组构成任务状态的字段:Int32的ID,Task执行状态的Int32,对父任务的一个引用,对Task创建指定TaskScheduler的一个引用,对回掉方法的一个引用,对传值给回调方法的对象一个引用,对一个ExecutionContext的引用,对ManualResetEventSlim对象的引用,以及一些补充状态的一个引用(CancellationToken,ContinueWithTask队形集合,异常Task集合)

         2,Task和Task<TResult>实现了IDisposeable接口,完成后调用Dispose

         任务工厂:

         TaskFactory 和 TaskFactory<TResult>类

          任务调度器:

          1,TaskScheduler对象负责任务调度,包含两个派生类:线程池任务调度器(thread pool task scheduler)和同步上下文任务调动起(sysnchronization context task scheduler)

    默认是前者调度器。后者应用于windows窗体,wpf和silverlight应用程序。

         Pareallel的静态For,ForEach 和Invoke方法:

         可以帮助提高性能。

     计算限制操作的定时器:

          System.Treading命名空间定义一个Timer类,可以让线程池线程定时调用搞一个方法。

          1,线程池为所有的Timer对象只是用了一个线程。这个线程知道下一个Timer对象什么时候触发

          2,当下一个Timer对象到期,线程就会唤醒,内部调用ThreadPool的QueueUserWorkItem(工作项),将工作项添加到线程池的队列中。然后等待回调。

          3,如果回调方法执行很长,计时器可能会再次触发 .Timeout.Infinite可让计时器只触发一次。

       

    线程池如何管理线程:

           1,System.Threading.ThreadPool类提供:GetMaxTreads,SetMaxThreads,GetMinThreads,SetMinThreads和GetAvailableThreads用于查询和设置线程池的线程数。但是,限制线程池的显成熟,会造成应用程序性能变得更差。

           2,ThreadPool.QueueUserWorkItem方法和Timer类将工作项放入全局队列中。工作者进程采用的先入先出(FIFO)

    算法将工作项取出,并处理他们。所有工作者线程都竞争一个线程同步所。

           3,TaskScheduler调度Task对象:非工作者调用Task对象----Task添加到全局队列----Task添加到调用线程的本地队列------工作线程准好处理工作项----检查本地队列查找一个Task------如果本地队列存在一个Task,就从本地队列移除Task,对工作项进行处理(工作者线程采用后入先出(LIFO)取出本地Task)

    缓存线和伪共享

              1,CPU在芯片上集成了高速缓存(Cache)使得CPU访问RAM速度非常快。

              2,CPU在逻辑上讲所有内存划分为“缓冲行”用于进一步提高性能。一个缓冲行由64个字节构成。

  • 相关阅读:
    【WPF】 前言
    【设计模式】 建造者
    拖动调整显示框的显示区域大小
    HTTP权威指南
    input自动获取焦点
    元素JS拖动的实现
    手机端html5触屏事件(touch事件)
    使用".."指定git提交范围与"..."指定git提交范围的区别
    Long-term stable release maintenance
    MEMS--微机电系统
  • 原文地址:https://www.cnblogs.com/changrulin/p/4786659.html
Copyright © 2011-2022 走看看