71, 区分异步和多线程的应用场景。

计算机的很多硬件,如硬盘,光驱,声卡,网卡都有DMA(Direct Memory Access)功能,它可以不占用cpu的资源,而异步的提出恰恰就是基于这个的。而多线程是操作系统上的并行执行的代码,是会占用cpu资源的。所以关于这两种的使用场景建议是:1)对于I/0密集型操作使用异步。2)对于计算密集型操作使用多线程。

72, 在线程同步中使用信号量。

值类型是不能被锁定的,引用类型上的等待机制,分为锁定和信号同步。锁定通过lock关键字或Monitor来完成;信号同步用AutoResetEvent,ManualResetEvent,Semaphore,Mutex,其中Mutex可以在不同进程间同步。

73, 避免锁定不恰当的对象。

同步对象在需要同步的多个线程中是可见的同一个对象,不要锁定字符串,类型本身,实例本身。降低同步对象的可见性,尽量让它变为private的。

74, 警惕线程的IsBackground。

用Thread类创建的线程是前台线程,如果前台线程不全部退出,应用程序就关不掉。而ThreaadPool里的线程默认是后台的。所以一些关键性的操作才需要前台线程,否则应将IsBackground设为true。

75, 警惕线程不会立即启动。

这取决于操作系统的调度,我们不能假设它会立即启动。

76, 警惕线程的优先级。

Thread和ThreadPool创建的线程优先级都是Nomal的,我们一般没有必要去修改这个优先级,对于Window操作系统,优先级越高在调度时会得到优先执行。

77, 正确停止线程。

1)正如线程不能立即启动一样,线程的停止也不是想停就能停,他必须做完必要的工作后才能停止,以传统的Thread.Abort方法为例,调用这个方法后,如果代码在和非托管代码打交道,只有等到这部分代码结束后才能引发ThreadAbortException,即便是在CLR环境中ThreadAbortException也不会立即引发。2)要正确停止线程,不在于调用者采取的行为(Abort),而更多的依赖于线程能否主动响应调用者的停止请求。线程应该开放一个Cancled接口,工作线程以某种频率检测Cancled标识,如果发生改变,线程自己负责退出。.net提供了一个CancellationTokenSource用于协作取消。cts.Token.IsCancellationRequested判断是否有取消操作,cts.Cancel()发送取消请求,线程结束时的如需回调,可以用cts.Token.Register(() => {// 回调 })注册一个回调函数;

78, 应避免线程数量过多。

对于Socket类型的操作应该用异步,而不要开线程。

79, 使用ThreadPool或BackgroundWorker替代Thread。

ThreadPool线程池可以重复利用空闲的线程。BackgroundWorker可以支持进度,完成通知,取消功能,内部也是用的线程池。

80, 用Task来替代ThreadPool。

Task在线程池的基础上进行了优化,Task提供了ContinueWith方法来提供后续任务的执行。Task提供了IsCanceled,IsCompleted,IsFaulted这几个属性用于查询任务的执行结果。并且还支持取消功能。Task的Result属性用于查询函数的返回结果,如果执行过程被取消,调用这个属性会引发AggregateException异常,Task比ThreadPool功能丰富了很多,应尽量多用Task。

81, 使用Parallel简化同步状态下的Task使用。

Parallel是一个静态类,提供了For,Foreach,Invoke方法启动多个Task执行任务。

82, Parallel简化但不等同于Task的默认行为。

Parallel的方法调用后是阻塞的,尽管他内部的Task是并行计算的,除非这些Task都执行完了,Parallel后面的代码才会得到执行。

83, 小心Parallel的陷阱。

Parallel的For方法还提供了线程开始前和结束后执行的方法。但由于Task使用的线程池,比如4次循环可能使用了1个或2个线程,这会带来这两个方法执行次数的不确定性。另外,toExclusive参数指定值为5的时候,循环结束的位置是它的前一个值4,而不是5。

84, 使用PLINQ。

PLINQ即并发执行的LINQ,由于是并发,对于大数据量的查询,它的效率可能会更好。要使用PLINQ,只用调用数据源的扩展方法AsParallel方法,在ForEach查询中,结果就会得到并行计算,当然输出是无序的。如果要按有序输出,可以在数据源上调用AsOrderd方法,如:arr.AsParallel().AsOrdered()。注意在查询的ForAll方法中,输出始终是无序的。关于PLINQ的使用,应该进行充分的学习了解后再使用,否则可能会带来意想不到的bug。

85, Task中的异常处理。

调用任务的Wait,WaitAny,WaitAll方法,或查询Result属性,如果Task发生了异常,会生成一个AggregateException,我们通过循环查询它的InnerException就可以知道所有的异常。但是Wait等方法是会阻塞主线程的。Task产生的异常,如果在Task内部没有得到处理,也没有抛给主线程的话,那么只有垃圾回收的时候才会触发TaskScheduler.UnobservedTaskException事件,如果调用了UnobservedTaskException的e.SetObserved();方法,异常就不会再往上传递,否则还会进一步触发CurrentDomain_UnhandledException事件,程序终止。所以,Task内部的异常应该立即得到处理。简单一点的做法是Task内部逻辑对捕获的异常进行处理,比如写日志之类的。另一种是,在外部定义一个事件,Task内部出现异常时,通过这个事件通知给外部,在这里进行异常的后续操作,这种方法比较可取。

86, Parallel中的异常处理。

Parallel中的异常和Task中的异常不一样。它可以抛出给主线程。但是我们也可以在内部声明一个AggregateExcption,把所有的异常捕获后,打包到AggregateExcption里面,一起抛出,个人感觉意义不大。

87, 区分Winform和WPF的线程模型。

Winform中是通过ISynchronizeInvoke接口的InvokeRequire属性来判断控件是否处在其他线程中。Winform中的所有控件都继承了这个接口。WPF中是通过DispatcherObject提供的CheckAccess和VerifyAccess方法来判断,其中VerifyAccess判断不是同一个线程会抛出异常。

88, 并行并不总是速度最快。

因为并行会带来额外的线程开销,对于小的循环体,计算量不大,并行反而会更慢。

89, 在并行方法中谨慎使用锁。

并行中有多个线程,加锁会带来线程的切换,影响性能。可以适当考虑用Interlock对整型进行原子加减操作而避免线程切换的开销。如果整个代码都是需要加锁的,那么实际上就没有并行的意义,用同步的方式或许会更好。

转载于:https://www.cnblogs.com/xiashengwang/p/4013687.html

【进阶修炼】——改善C#程序质量(5)相关推荐

  1. pandas 取excel 中的某一列_Pandas进阶修炼120题,给你深度和广度的船新体验

    Pandas 是基于 NumPy 的一种数据处理工具,该工具为了解决数据分析任务而创建.Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的函数和方法. 和鲸社区的@刘早起 ...

  2. 我的Android进阶修炼:安卓启动流程之init(1)

    文章目录 我的Android进阶修炼:安卓启动流程之init(1) 一.前言 二.init进程简介 1.文件位置 2.主要功能 三.init进程源码分析 3.1 main() 源码注解 3.1.1 参 ...

  3. Pandas进阶修炼120题

    作者:刘早起 来源:早起python,禁止二次转载 这篇文章是『Pandas进阶修炼120题』的汇总,我们对Pandas中常用的操作以习题的形式发布.从读取数据到高级操作全部包含,希望可以通过刷题的方 ...

  4. 【进阶修炼】——改善C#程序质量(9)

    140,使用默认的访问修饰符. 如果不加访问修饰符,成员变量的默认是private的,类默认是internal的.为了明确访问的权限,我倒是建议都加上访问修饰符,这省不了多少代码. 141,不知道该不 ...

  5. HTML从入门到进阶修炼

    HTML修炼之路:http://www.w3school.com.cn/html/index.asp

  6. Pandas进阶修炼120题,给你深度和广度的船新体验

    来源:早起Python 本文约5800字,建议阅读15分钟. 本文为你介绍Pandas基础.Pandas数据处理.金融数据处理等方面的一些习题. Pandas 是基于 NumPy 的一种数据处理工具, ...

  7. java awt 仿360 进度_Android 控件进阶修炼-仿360手机卫士波浪球进度控件

    一.概述 像360卫士的波浪球进度的效果,一般最常用的方法就是 画线的方式,先绘sin线或贝塞尔曲线,然后从左到右绘制竖线,然后再裁剪圆区域. 今天我这用图片bitmap的方式,大概的方法原理是: ( ...

  8. pandas计算含缺失值中列平均值_Pandas进阶修炼120题,给你深度和广度的船新体验...

    来源:早起Python 本文约5800字,建议阅读15分钟. 本文为你介绍Pandas基础.Pandas数据处理.金融数据处理等方面的一些习题. Pandas 是基于 NumPy 的一种数据处理工具, ...

  9. GaussDB数据库培训服务上线,技能进阶修炼正当时

    近日,华为云宣布GaussDB数据库培训服务上线,面向高校师生和企业开发/运维人员提供专业的数据库培训服务. 本次上线的数据库培训服务主要包括华为openGauss数据库工程师培训(HCIA-open ...

  10. python一百天:从小白到大师的进阶之路

    当编程小白问怎么自学的时候,他其实是缺一套课程入门. 当编程熟手问怎么自学的时候,他其实是缺几个项目练手. 当编程大佬问怎么自学的时候,他其实是缺一点深度知识. 当所有人还在问怎么自学Python,学 ...

最新文章

  1. 12种主要的Dropout方法:用于DNNs,CNNs,RNNs中的数学和可视化解释
  2. 【Android 内存优化】Android 原生 API 图片压缩代码示例 ( PNG 格式压缩 | JPEG 格式压缩 | WEBP 格式压缩 | 动态权限申请 | Android10 存储策略 )
  3. 将一个Excel文件分隔成多个
  4. 【学习笔记】智能制造之精益思想
  5. 进入全真互联网——音视频通信的技术变革
  6. Hive中的一种假NULL
  7. motion的移植和使用
  8. SaveRasterFile failed: IDLnaMetadata Error:naGetMetadata-GetMetadataJob failed
  9. location 获取参数和锚_window.location获取url各项参数详解
  10. 轴承公差以及常见的轴孔公差配合
  11. 一部手机即可轻松玩转抖音四大主流变现方式——匀思电商
  12. 深度学习图形工作站环境安装与配置(1)CUDA和cuDNN的安装
  13. 如何在Win11中恢复动态磁贴?
  14. docker打包镜像--go语言编写的http项目
  15. CityEngine学习资料——
  16. 新华三:助力IPv6部署,我们责无旁贷
  17. 测试中遇到的bug总结
  18. 滴滴云GPU服务器做深度学习之tensorflow object detect 对象检测 实践
  19. python向上取整_python向上取整
  20. SQLServer阻止保存要求重新创建表的更改,sql在一列数据前统一加字符

热门文章

  1. efi分区能不能删除 win10_电脑分区被删除如何恢复_win10系统中EFI分区被删除的处理方法...
  2. php 便利字符串,Go语言遍历字符串——获取每一个字符串元素
  3. easydarwin 安装_在Linux平台上搭建EasyDarwin,编译代码并简单部署
  4. 上海戏剧学院开学计算机考试,2021年上海戏剧学院大一新生转专业及入学考试相关规定...
  5. 常用linux命令分组记录V1
  6. python 列表相关应用大全
  7. mysql 解压版安装及DATA初始化 root用户密码修改
  8. IOS 中description 和 debugDescription的区别
  9. tomcat,tomcat7配置https
  10. sqlite3的命令简单说明