线程也疯狂------计算限制的异步操作

参考页面:

http://www.yuanjiaocheng.net/webapi/create-crud-api-1.html

http://www.yuanjiaocheng.net/webapi/create-crud-api-1-get.html

http://www.yuanjiaocheng.net/webapi/create-crud-api-1-post.html

http://www.yuanjiaocheng.net/webapi/create-crud-api-1-put.html

http://www.yuanjiaocheng.net/webapi/create-crud-api-1-delete.html

前言

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

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)

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

时间: 2024-10-19 11:27:49

线程也疯狂------计算限制的异步操作的相关文章

【C#进阶系列】26 计算限制的异步操作

什么是计算限制的异步操作,当线程在要使用CPU进行计算的时候,那么就叫计算限制. 而对应的IO限制就是线程交给IO设备(键鼠,网络,文件等). 第25章线程基础讲了用专用的线程进行计算限制的操作,但是创建专用线程开销大,而且太多的线程也浪费内存资源,那么本章就讨论一种更好的方法,即线程池技术. CLR线程池 CLR包含了代码来管理它自己的线程池.线程池是应用程序能使用的线程集合,每个CLR一个线程池,这个线程池由CLR上所有的AppDomain共享. CLR初始化时线程池中没有线程. 在线程池内

线程也疯狂------线程基础

参考页面: http://www.yuanjiaocheng.net/webapi/web-api-gaisu.html http://www.yuanjiaocheng.net/webapi/create-web-api-proj.html http://www.yuanjiaocheng.net/webapi/test-webapi.html http://www.yuanjiaocheng.net/webapi/web-api-controller.html http://www.yuan

线程也疯狂-----异步编程

前言 本节主要介绍异步编程中Task.Async和Await的基础知识. 什么是异步? 异步处理不用阻塞当前线程来等待处理完成,而是允许后续操作,直至其它线程将处理完成,并回调通知此线程. 异步和多线程 相同点:避免调用线程阻塞,从而提高软件的可响应性. 不同点: 异步操作无须额外的线程负担,并且使用回调的方式进行处理,在设计良好的情况下,处理函数可以不必使用共享变量(即使无法完全不用,最起码可以减少 共享变量的数量),减少了死锁的可能.C#5.0 .NET4.5 以后关键字Async和Awai

26计算限制的异步操作-CLR

由CLR via C#(第三版) ,摘抄记录... 异步优点:在GUI应用程序中保持UI可响应性,以及多个CPU缩短一个耗时计算所需的时间. 1.CLR线程池基础:为提高性能,CLR包含了代码来管理他自己的线程池--线程的集合.每CLR一个线程池,这个线程池就由CLR控制的所有appDomain共享.如果你进程中有多个CLR,就有多个线程池. CLR初始化时,池空,线程池维护一个操作请求队列.应用调用方法执行异步,将一个记录项(entry)追加到线程池的队列.线程池从队列提取记录项,派遣(dis

Clr Via C#读书笔记---计算限制的异步操作

线程池基础 1,线程的创建和销毁是一个昂贵的操作,线程调度以及上下文切换耗费时间和内存资源. 2,线程池是一个线程集合,供应你的用程序使用. 3,每个CLR有一个自己的线程池,线程池由CLR控制的所有的AppDomain共享. 4,CLR初始化的时候,线程池没有线程的. 5,线程池维护一个操作请求队列.当应用程序想要执行一个一步操作的时候,就调用某个方法.将记录项(empty)追加到线程池队列中,然后线程池代码从队列中提取这个记录项,然后将记录项派遣(dispatch)给一个线程池的线程.当线程

java8--多线程(java疯狂讲义3复习笔记)

多线程这块,平时用的框架里都封装好了,只有写批处理和工具包时用过几次.现在水平仅仅限于会用的程度,需要全面深入学习多线程. 主要内容:创建线程,启动线程,控制线程,多线程的同步,线程池,使用线程安全的集合类 16.1.1 线程和进程 线程是进程的组成部分,一个进程可以拥有多个线程,一个线程必须有一个父进程.线程可以拥有自己的堆栈,程序计数器和局部变量,但不拥有系统资源,它与父进程的其他线程共享该进程所拥有的全部资源.因为多个线程共享父进程的全部资源,因此编程更加方便,带也需要更加小心. 16.2

使用线程池与专用线程

高效线程使用圣典 严格来讲,线程的系统开销很大.系统必须为线程分配并初始化一个线程内核对象,还必须为每个线程保留1MB的地址空间(按需提交)用于线程的用 户模式堆栈,分配12KB左右的地址空间用于线程的内核模式堆栈.然后,紧接着线程创建后,Windows调用进程中每个DLL都有的一个函数来通知进程 中所有的DLL操作系统创建了一个新的线程.同样,销毁一个线程的开销也不小:进程中的每个DLL都要接收一个关于线程即将"死亡"的通知,而且内核对象 及堆栈还需释放. 如果一台计算机中只有一个C

.NET线程控制快速学习01

最近,由于基础框架的整体升级,因此需要更新所有相关项目的DLL文件.这个过程存在不小的风险,因此也对发布后的生产服务器进行了密切的监控,结果还是出现了个别应用出现异常的情况,很快的占用了大量的服务器内存和CPU等资源.通过研究dump,初步发现是由于配置服务器出现单点故障,然后应用通过多线程调用相关SOA服务时出现异常,引发了ThreadAbortException异常,而且由于原有异常处理代码不够严谨,而且与异步发送报警邮件紧密结合在一起,造成线程数量的几何级增加,最终使得整个服务器不可用.这

读书笔记—CLR via C#线程25-26章节

前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可以加深自己理解的深度,当然同时也和技术社区的朋友们共享 线程 线程内部组成 线程内核对象 thread kernel object,在该结构中,包含一组对线程进行描述的属性.数据结构中还包括所谓的线程上下文thread context.上下文是一个内存块,包含了CPU的寄存器集合,占用几百到几千个字