zoukankan      html  css  js  c++  java
  • 线程也疯狂计算限制的异步操作

    前言

    异步的限制操作主要作用于其他执行线程,例如规则检查、音频或视频数据转码以及生成图形略缩图,在金融和建筑工程应用程序中,计算限制的操作也是十分普遍的。

    CLR线程池

    线程池是你的应用程序能使用的线程的一个集合,每个线程池都是由CLR控制的所有AppDomain共享,如果一个进程加载了多个CLR,那么每个CLR都有它自己的线程池,CLR初始化时,线程池中本来没有线程,线程池的内部维护了一个队列请求,应用程序执行一个异步时,就调用某个方法,将一个记录项追加到线程池的队列中,线程池的代码从这个队列中提取记录项,将这个记录项派发给一个线程池线程,如果线程池中没有线程就创建新的线程,当任务执行后,线程并不会销毁,返回线程池,进入空闲状态,等待响应另一个请求,不再消耗额外的性能。

    但是当一个线程闲着没事儿一段时间后,线程会自动释放资源,使用线程池的目的就是不用担心线程创建和销毁带来的性能损失。

    简单的计算限制操作

    ThreadPool类定义的一个方法:

    static Boolean QueueUserWorkItem(WaitCallback callBack,object obj);

    方法说明:向线程池中添加一个工作项以及可选的状态数据,然后执行此工作项,可向方法传递一个obj参数

    代码演示

     1 class Program
     2     {
     3         static void Main(string[] args)
     4         {
     5             Console.WriteLine("程序开始执行");
     6             ThreadPool.QueueUserWorkItem(ComputerSort, 6);
     7             Console.WriteLine("模拟其他操作执行5s");
     8             Thread.Sleep(5000);
     9             Console.WriteLine("点击Enter退出程序");
    10             Console.ReadLine();
    11         }
    12 
    13         private static void ComputerSort(object obj)
    14         {
    15             Console.WriteLine("线程池开始执行 参数={0}",obj.ToString());
    16         }
    17     }

    显示结果

    我们发现输出的执行顺序会发生变化,是因为两个方法相互之间在异步上运行的,Windwos调度器决定具体先调度那个线程,如果是多核CPU可能同时调度它们。

    执行上下文

    每个线程都关联两个一个执行上下文数据结构,执行上下文包括:安全设置(压缩栈、Principal属性、Windows身份)、宿主设置以及逻辑调用上下文数据。

    理想情况下,每当一个线程使用另一个线程(辅助线程)执行任务时,前者的执行上下文应该流向后者,确保辅助线程执行的操作都是使用的相同安全设置和宿主设置。

    通过阻止执行上下文流动可以提升应用程序的性能,尤其是服务器应用性能提高显著,客户端的效果一般。

    事例代码:

     1  static void Main(string[] args)
     2         {
     3 
     4             //将数据放入Main线程的逻辑上下文中
     5             CallContext.LogicalSetData("Name","Tom");
     6 
     7             ThreadPool.QueueUserWorkItem(p =>
     8             {
     9                 Console.WriteLine("Name = {0}",CallContext.LogicalGetData("Name"));
    10             });
    11 
    12             ExecutionContext.SuppressFlow();
    13 
    14             ThreadPool.QueueUserWorkItem(p =>
    15             {
    16                 Console.WriteLine("Name = {0}", CallContext.LogicalGetData("Name"));
    17             });
    18 
    19             ExecutionContext.RestoreFlow();
    20 
    21             ThreadPool.QueueUserWorkItem(p =>
    22             {
    23                 Console.WriteLine("Name = {0}", CallContext.LogicalGetData("Name"));
    24             });
    25 
    26             Console.ReadLine();
    27 
    28         }

    协作式取消和超时

    对于长时间运行的计算限制操作,支持取消是一个必要的操作,.Net提供了标准的取消操作模式,无论执行操作的代码,还是试图取消操作的代码,都必须使用下面介绍的类型。

    System.Threading.CancellationTokenSource------->这个对象包含了管理取消有关的所有状态,可以从它的Token属性获得一个或者多个CancellationToken实例,

     1  static void Main(string[] args)
     2         {
     3             CancellationTokenSource  cts = new CancellationTokenSource();
     4 
     5             ThreadPool.QueueUserWorkItem(state => Count(cts.Token, 100));
     6 
     7             Console.WriteLine("输入Enter停止计算");
     8 
     9             Console.ReadLine();
    10 
    11             cts.Cancel();
    12 
    13             Console.ReadLine();
    14         }
    15 
    16         private static void Count(CancellationToken token,int count)
    17         {
    18             for (int i = 0; i <=count; i++)
    19             {
    20                 if (token.IsCancellationRequested)
    21                 {
    22                     Console.WriteLine("接收到取消信号");
    23                     break;
    24                 }
    25                 Console.WriteLine("i = {0}",i);
    26                 Thread.Sleep(1000);
    27             }
    28         }

    如果愿意可调用CancellationTokenSource的Register方法登记一个或者多个在取消一个CancellationTokenSource时调用的方法,要向方法传递一个Action<object>委托,一个要通过委托方法传给回调,以及一个Boolean值,该值指明是否要使用调用线程的SynchroinzationContent来调用委托。

    1  cts.Token.Register(() =>
    2             {
    3                 Console.WriteLine("接收到取消信号后,开始调用回调函数");
    4             });

     在很多情况下,我们需要在过一段时间之后才取消操作,例如服务器应用程序可能会根据客户端的请求进行计算,但必须在两秒内响应,无论是否完成必须结束此次会话。在.NET 4.5中,CacncellationTokenSource提送了一个CancelAfter的方法

    1  public void CancelAfter(int millisecondsDelay)

    本章节的内容就讲解到这里,下节我们将会继续 线程也疯狂-----异步编程。

  • 相关阅读:
    Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging
    KDiff3使用指南
    Win10解决修改host没有权限问题(其他文件同理) 一步都不能少哦:先添加再授权
    微信小程序
    MyBatisSystemException 【exception】
    [LeetCode] Additive Number 加法数
    [CareerCup] 14.5 Object Reflection 对象反射
    C Memory Layout C语言中的内存布局
    strtol 函数用法
    [CareerCup] 14.4 Templates Java模板
  • 原文地址:https://www.cnblogs.com/dongqinnanren/p/6255038.html
Copyright © 2011-2022 走看看