偶然遇到在执行登陆的方法须要发送消息队列致使登陆时间过长的问题,从网上查了一些方法,先将一个简单的异步处理程序的小例子展现出来,供你们参考:html
备注:该方法是从应用程序程序所在的线程池中获取线程,第一次建立异步线程可能会费用一些时间,建立后不会当即销毁,以便其余线程屡次重复使用,对程序性能影响不大:git
//异步执行修改用户登陆时间并发送队列--20171209-lixh Task.Run(() => { UserInfoBIZ.UpdateUserInfo(userInfo, ConfigSetting.SITEID, ConfigSetting.WEB_SITE_NAME, EPlatform.PC端); });
本文转载地址:http://www.javashuo.com/article/p-mbonqvcu-x.htmlgithub
如下是转载全文:数据库
以前写程序的时候在遇到一些比较花时间的操做例如HTTP请求时,老是会new一个Thread处理。对XxxxxAsync()之类的方法也没去了解过,倒也没遇到什么大问题。最近由于需求要求用DevExpress写界面,跑起来后发现比Native控件效率差好多。这才想到以前看到的“金科玉律”:不要在UI线程上执行界面无关的操做,所以集中看了下C#的异步操做,分享一下本身的比较和总结。并发
IDE:VS2015 Community异步
.NET版本:4.5async
使用函数随机休眠100到500毫秒来模拟耗时任务,并返回任务花费的时间,在UI线程上调用这个方法会形成阻塞,致使UI假死,所以须要经过异步方式执行这个任务,并在信息输出区域显示花费的时间。函数
主界面中经过各类不一样按钮测试不一样类型的异步操做性能
使用ThreadPool进行异步操做的方法以下所示,须要注意的就是IsBackground默认为false,也就是该线程对调用它的线程不产生依赖,当调用线程退出时该线程也不会结束。所以须要将IsBackground设置为true以指明该线程是后台线程,这样当主线程退出时该线程也会结束。另外跨线程操做UI仍是要借助Dispatcher.BeginInvoke(),若是须要阻塞UI线程可使用Dispatcher.Invoke()。测试
ThreadPool(线程池)的出现主要就是为了提升线程的复用(相似的还有访问数据库的链接池)。线程的建立是开销比较大的行为,为了达到较好的交互体验,开发中可能会大量使用异步操做,特别是须要频繁进行大量的短期的异步操做时,频繁建立和销毁线程会在形成不少资源的浪费。而经过在线程池中存放一些线程,当须要新建线程执行操做时就从线程池中取出一个已经存在的空闲线程使用,若是此时没有空闲线程,且线程池中的线程数未达到线程池上限,则新建一个线程,使用完成后再放回到线程池中。这样能够极大程度上省去线程建立的开销。线程池中线程的最小和最大数均可以指定,不过多数状况下无需指定,CLR有一套管理线程池的策略。ThreadPool的使用很是简单,代码以下所示。跨线程操做UI仍需借助Dispatcher。
Task进行异步操做时也是从线程池中获取线程进行操做,不过支持的操做更加丰富一些。并且Task<T>能够支持返回值,经过Task的ContinueWith()能够在Task执行结束后将返回值传入以进行操做,但在ContinueWith中跨线程操做UI仍需借助Dispatcher。另外Task也能够直接使用静态方法Task.Run<T>()执行异步操做。
这个是C#5中的新特性,当遇到await时,会从线程池中取出一个线程异步执行await等待的操做,而后方法当即返回。等异步操做结束后回到await所在的地方接着日后执行。await须要等待async Task<T>类型的函数。详细的使用方法可参考相关资料,测试代码以下所示。异步结束后的会返回到调用线程,因此修改UI不须要Dispatcher。
也能够把TestTask包装成async方法,这样就可使用上图中注释掉的两行代码进行处理。包装后的异步方法以下所示:
async/await也是从线程池中取线程,可实现线程复用,并且代码简洁容易阅读,异步操做返回后会自动返回调用线程,是执行异步操做的首选方式。并且虽然是C#5的新特性,但C#4能够经过下载升级包来支持async/await。
以上尝试的方法除了直接使用Thread以外,其余几种都是直接或间接使用线程池来获取线程的。从理论上来分析,建立线程时要给线程分配栈空间,线程销毁时须要回收内存,建立线程也会增长CPU的工做。所以能够连续建立线程并记录消耗的时间来测试性能。测试代码以下所示:
当测试Thread时每次测试在连续建立线程时内存和CPU都会有个小突起,不过在线程结束后很快就会降下去,在个人电脑上连续建立100个线程大概花费120-130毫秒。如图所示:
测试结果:
使用基于线程池的方法建立线程时,有时第一次会稍慢一些,应该是线程池内线程不足,时间开销在0-15毫秒,第一次建立内存也会上升。后面再测试时时间开销为0毫秒,内存表现也很平稳,CPU开销分布比较平均。测试结果如图所示:
在执行异步操做时应使用基于线程池的操做,从代码的简洁程度和可读性上优先使用async/await方式。对于较老的.NET版本可使用Task或ThreadPool。符合如下状况的可使用Thread:
一、线程建立后须要持续工做到主线程退出的。这种状况下就算使用线程池线程也不会归还,实现不了复用,可使用Thread。
二、线程在主线程退出后仍须要执行的,这种状况使用线程池线程没法知足需求,须要使用Thread并制定IsBackground为false(默认)。
测试程序代码在:https://github.com/durow/TestArea/tree/master/AsyncTest/AsyncTest