很久不写博客了,不是因为不想写,只是最近公司任务比较多,终于十一有时间出来冒泡了。

今天继续介绍移动开发中的重中之重——内存管理。
C#代码是托管代码,C# 程序员很少像C/CPP程序员那样为程序资源的释放而头疼,一个C/CPP高手必须是内存管理的高手,作为C#程序虽然不要求像C/CPP程序员那样管理内存资源,但是对内存机制还需要有深入的理解,那些代码资源是托管资源交给GC去处理,那些资源需要程序员手工释放,当然大家更关心的是非托管资源,因为托管资源GC会自动清理。
一般查看一个类是否是托管资源通常可以这样做,在VS里F12转到定义,查看类或父类是否实现了IDisposable接口,所有实现了IDisposable接口的类都需要手动释放资源,GC是不会清理这些资源的,在C#中实现了IDisposable接口常见的类有:数据库连接父类DbConnection以及各种数据库Adapter,Command等类,各种文件流父类Stream等类。
对于这些类,我们有两种策略。
策略一:
      在我们使用这些类的时候都用try...catch...finally语句,在finally里面进行释放资源。具体做法如下:
public class SqlHelper
{//获取配置文件中的数据库连接字符串private static readonly string ConnStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;/// <summary>/// 支持存储过程的通用返回DataTable的数据库参数查询方法/// </summary>/// <param name="sqlstr">查询SQL字符串</param>/// <param name="cmdtype">命令类型</param>/// <param name="paras">参数</param>/// <returns>DataTable结果集</returns>public static DataTable ExecuteDataTable(string sqlstr, CommandType cmdtype, params SqlParameter[] paras){//创建实现IDisposable接口类对象SqlDataAdapter adapter = null;try{adapter = new SqlDataAdapter(sqlstr, ConnStr);DataTable dt = new DataTable();adapter.SelectCommand.CommandType = cmdtype;if (paras != null && paras.Length > 0){adapter.SelectCommand.Parameters.AddRange(paras);}adapter.Fill(dt);//执行到此,adapter已经用完return dt;}catch(Exception e){//记录错误日志等操作return null;}finally{//释放非托管资源adapter.Dispose();}}
这样,当我们在调用SqlHelper的ExecuteDataTable方法的时候,我们就不必在关心Adapter对象资源的释放,finally语句会在我们用完Adapter的时候自动将资源释放,这样虽然满足了我们的要求,但是这样似乎有点麻烦,好的。
策略二:
  那就用C#的using语句,具体如下:
 public static DataTable ExecuteDataTable(string sqlstr, CommandType cmdtype, params SqlParameter[] paras){//实现了IDisposable接口的类对象using (SqlDataAdapter adapter = new SqlDataAdapter(sqlstr, ConnStr)){DataTable dt = new DataTable();adapter.SelectCommand.CommandType = cmdtype;if (paras != null && paras.Length > 0){adapter.SelectCommand.Parameters.AddRange(paras);}adapter.Fill(dt);return dt;}}

这样写比用try..finally方便了许多,只要using实现IDisposable接口的对象,using语句块走完IDisposable对象会被自动释放,注意,没有实现IDispoable接口的类是不能被using的,其实using内部也是try...catch...finally的实现,只是微软给封装好了,这也是C#程序员专有的语法糖。
当然,如果你也想实现IDisposable接口,能够被using,那么你就参考微软MSDN建议的示例就可以了,我在这里就不多墨迹了。
说完非托管对象,该说托管对象,托管对象完全交由CLR的GC统一管理,那么什么时候GC会回收一下托管资源呢?
所谓托管资源,没有实现IDisposable接口的一般类,没有文件和数据库操作等,例如,int,string,List等,当我们在使用这些对象时,我们不需要关心他们的释放,他们会由GC统一处理,一般如果系统内存够用GC就不会回收这些托管资源,当内存紧张时GC会回收那些没有任何引用指向的对象,当然C#也给程序员提供了手动调用GC回收的方法,GC.Collect()方法,但是即使程序员即使手动调用了该方法,GC也不一定在那一时刻对托管资源进行回收,另外Collect()方法不建议程序员手动的调用,如果频繁调用会严重拖垮程序的性能,因为内存频繁的回收,C#有三级垃圾回收,想了解的可以百度一下。
在网站的开发中,往往愿意牺牲适当的内存来提高网站的性能,因为内存的存取速度远远超过磁盘的速度,这样会缓解网站大并发带来的压力,因此也产生了一批Memcached、Redis等服务器内存管理软件,甚至MySql数据库也可以把数据存储在内存中,当然服务器重启内存数据一般就无法恢复了(Redis可以恢复),因此应该把什么数据放到内存中是开发的关键。
做为移动开发人员,对于内存的管理更是非常重要的。因为我们不像网站服务器有那么大的内存,目前来看,我听说的内存最大的莫过于微软的Surface Pro3,这是平板电脑的配置,但是如果是手机呢?最大的应该是小米的第4代手机3G内存,然后目前主流手机的内存应该在1.5G左右,苹果的手机内存要更小,面对这么小的内存,程序员开发时就一定要把握内存的使用。
既然手机内存那么小,是不是我把所有的资源使用后就立马释放就好呢?这样最节省资源啊?其实不是,这要根据具体的需求来定,有些情况下我们可以把一些常用的资源暂时放在内存中,等再次使用时从内存中调用可以大大提高程序的调用的速度,这里我们可以借助Framework的线程池原理,如果线程池里有线程对象,就用线程池里的对象,没有再开启一个新的线程。
这里必须要说的一个重要的知识点即使弱引用,WeakReference类的原理是,将对象用WeakReference指向,然后将那个对象是置为null(被GC发现可以及时回收),我们在使用的时候直接使用WeakReference对象指向的对象就可以了,WeakReference会自动管理对象,当内存中有需要的对象,就直接使用,没有就在内存中创建一个,具体使用方法如下:
object obj = new object();//对象由弱引用指向WeakReference wref = new WeakReference( obj );//将对象置为nullobj = null;//使用弱引用指向的对象object currObj=wref.Target;//使用currObj完成业务

关于弱引用就简单的介绍到这里,当然弱引用的使用也不仅仅只是这些,还有很多,大家可以自己搜索一下,我就不过多介绍了,在后来的Windows Store应用开发里我会具体的举出弱引用的具体应用场景。如果想深入理解内存的使用,建议去网上看吕建中的设计模式视频中的享元模式,享元模式讲的是内存的共享,其实开发中很多东西都可以共享,深入理解池的概念很重要。
好了,今天就到这里,我们下期见。

Windows移动开发(四)——闭关修炼相关推荐

  1. Windows移动开发(二)——闭关修炼

    一些武侠小说里的大人物,为了争夺武林盟主,号召天下,经常闭关修炼一段时间,闭关期间只能接触送饭的人,并且关外还有很多守卫的人员.还有,无论是篮球还是足球运动员,他们在真正接触球之前,都必须做很长一段时 ...

  2. Windows移动开发(三)——闭关修炼

    上一次,我们了解了委托,委托和Lambda表达式结合是一件灰常灰常爽的事情,这也是只有.Net才有,自己偷着笑去吧.几天这次,我要介绍一下继承和多态,这是进行面向对象编程必须熟练掌握的技术和思想. 1 ...

  3. Windows驱动开发学习笔记(四)—— 3环与0环通信(常规方式)

    Windows驱动开发学习笔记(四)-- 3环与0环通信(常规方式) 设备对象 创建设备对象 设置数据交互方式 创建符号链接 IRP与派遣函数 IRP的类型 其它类型的IRP 派遣函数 派遣函数注册位 ...

  4. 【软件开发底层知识修炼】二十四 ABI之函数调用约定

    上一篇文章学习了Linux环境下的函数栈帧的形成与摧毁.点击链接查看相关文章:软件开发底层知识修炼]二十三 ABI-应用程序二进制接口三之深入理解函数栈帧的形成与摧毁 本篇文章继续学习ABI接口相关的 ...

  5. 【软件开发底层知识修炼】十七 快速学习GDB调试四 使用GDB进行函数调用栈的查看

    上一篇文章学习了如何使用GDB数据断点进行内存监测:[软件开发底层知识修炼]十五 快速学习GDB调试三 使用GDB的数据断点监测变量是否改变 本篇文章继续上一篇文章的学习:如何使用GDB进行函数调用栈 ...

  6. 【软件开发底层知识修炼】十四 快速学习GDB调试一 入门使用

    前面几篇文章学习了链接器相关的内容.现在开始来学习GDB调试.我们的目的是通过这几篇文章将GDB调试完全学会. 文章目录 1 为什么需要GDB 2 GDB 的常规应用 3 GDB调试程序实例 4 总结 ...

  7. 十月一“闭关修炼”,读完这些Java技术栈,愿金九银十过五斩六

    十月一由于疫情还是有很多人为了安全不会去旅游,实际上,对于有跳槽打算的人来说,现在正是"闭关修炼"的好时机,但很多人不知道从何开始学习,也正为即将到来的金九银十发愁!今天,小编就要 ...

  8. Java闭关修炼64课 很适合新手学习的JAVA视频教程

    Java闭关修炼64课 很适合新手学习的JAVA视频教程 java闭关修炼第一课 什么是java(1).rar   java闭关修炼第一课 什么是java.rar   java闭关修炼第七课 基础语言 ...

  9. 开始闭关修炼 冥思微软之大未来

    盖茨开始闭关修炼 冥思微软之大未来 (2005.03.30)   华尔街日报   <script src="/adv/news_ad.asp?news_id=20356&sub ...

  10. 盖茨开始闭关修炼 冥思微软之大未来

    盖茨开始闭关修炼 冥思微软之大未来 http://www.csdn.net/news/newstopic/20/20356.shtml 上个月,如果你有机会一窥蕴藏了科技行业未来的水晶球,那么就会看到 ...

最新文章

  1. 9.1-全栈Java笔记: 容器泛型—认识Collection接口
  2. 算法设计原则验证实验报告_算法设计与分析实验报告 统计数字问题
  3. 枚举值转换(字符串转换为枚举和整数转换为枚举)
  4. 7个GIF动图帮你瞬间理解三角函数
  5. linux之文件类型
  6. python 属性描述符_Python属性描述符(二)
  7. unicode解码php,PHP解码unicode编码的中文字符
  8. Spring Boot细节挖掘(拦截器)
  9. shell调用python脚本传递命名关键字参数_关于python:将字典作为关键字参数传递给函数...
  10. Kotlin 函数(普通函数)
  11. 基于Java的汽车租赁系统
  12. QML Math详解 生成随机数
  13. C专家编程 五 声明的优先级规则
  14. 计算机软件比赛团队名称,辩论赛 | 最佳人气团队评选
  15. [Javascript 高级程序设计]学习心得记录10 js函数表达式
  16. 政策解读 | 传言PayPal要封杀独立站卖家?绝对不可能!
  17. 随机搜索(Random Searching)算法
  18. php如何做7天后自动售货店,PHP自动售货发卡网源码集成多种支付接口
  19. openssl给内网IP生成ca证书(ssl证书)
  20. Blinker点灯科技绑定GitHub增加设备数量到10个

热门文章

  1. proteus三输入与非门名字_proteus元件名称对照表
  2. 手机信令数据怎么获得_手机信令数据辅助下的张江科学城职住分析及对策 | 上海城市规划...
  3. Linux省级精品课程申报,2016年度省级精品在线开放课程开始申报啦!
  4. 做开发很久了 Remoting 一直没有碰过,正好最近的项目上面用,就拿出来给大家看看
  5. 无名接口.php,李无名
  6. linux 用户设密码,linux 上添加用户,设置密码
  7. 导入php插件_漏洞分析丨WordPress评论插件wpDiscuz任意文件上传
  8. 从决策树学习谈到贝叶斯分类算法、EM、HMM - 结构之法 算法之道
  9. 跳转html时请求头怎么取,如何获取a链接的请求头信息?
  10. python的copy模块是哪个模块_每周一个 Python 模块 | copy