实习总结:c#开发之旅(三)多线程小结(一)

      由于子系统中的任务,需要处理的数据量比较大,为了提高系统工作效率,老大要求使用多线程来执行任务,而我刚好负责流程控制这一块,当时真是被多线程折腾的死去活来,这个系统其实是有原型可以参考的,而且这个原型系统是久经考验,稳定性也很高;所以老大给我的时间并不多,我当时也没意识到难度会如此之大,但原型使用的是单线程,很多模块在单线程下跑得很欢,一到多线程就各种难了。

其实现在想来,使用多线程并行处理数据,真心不算个好的决定。

多线程适合处理的任务性质多为耗时的等待,或轮询判断状态。而此数据管理系统的瓶颈却是cpu运算和硬盘数据传输速度,后来测试结果也显示,多线程对性能的提升并不算太明显。当然这个不是主要原因,如果把系统布在强大的服务器上,性能提升还是有的。

更主要的原因是:数据处理任务太不原子化了(额 不知道原子化的反义词是什么),线程安全程度非常低。详细说明下就是,任务执行的过程中,和太多其他模块有太多的交互了,而且大量使用了全局变量(比如处理任务需要的各种参数、配置、执行方案)和静态变量(数据库操作类的静态实例),一旦跑起多线程,就各种并发冲突。当时我又没有很清晰的意识到这个问题,于是到处加锁,在dal入口加锁,在任务存取数据的地方加锁,在使用DBHelper的静态对象地方加锁,搞得这部分异常复杂,而且加太多锁的后果就是性能进一步的下降,搞得几乎和单线程效率差不多了。

额,说了半天废话,还没进入主题,有时间再接着整理(写)吧。


(待续)

这几天比较事多,今天有点功夫,接着写吧,

其实让线程跑起来倒是不难,


 Thread thread1 = new Thread(delegate())

       {    //功能函数体               });

       thread1.Start();  这是匿名方法创建线程,当然,也可以先实例化delegate。一样的。

也可以使用 ThreadPool.QueueUserWorkItem(DoDeleteInvoke)的方式。

难就难在 thread的控制上,一般来说,如果要对线程执行的情况进行监控,控制,多使用前者。

比如我需要根据用户设置,可以随时对线程进行挂起、恢复和销毁,基本就只能靠前者的方式了。

最开始的时候,我是检查ThreadState然后使用Suspended和Resume方法,遇到了很多问题。

//调用Resume方法可以恢复一个被延迟的线程。如果线程没有被延迟,Resume方法就是无效的。
if (thread.ThreadState = ThreadState.Suspended){
  thread.Resume();
}

引用msdn:

“只在少数几个调试方案中涉及线程状态枚举。您的代码在任何情况下都不应使用线程状态来同步线程的活动。”

Thread .Suspend 和 Thread .Resume 方法通常并不是对所有应用程序都有用,并且不应将其与同步机制混淆。 由于 Thread .Suspend 和 Thread .Resume 不依赖于受控制线程的协作,因此,它们极具侵犯性并且会导致严重的应用程序问题,如死锁(例如,如果挂起的线程占有另一个线程需要的资源,就会发生这种情况)。”

 

 

Thread有个threadState属性代表了线程的状态信息

可以通过这个属性判断线程当时的状态,

当一个thread实例刚创建时,他的threadstate是unstarted;当此线程被调用start()启动之后,他的threadstate是 running; 在此线程启动之后,如果想让他暂停(阻塞),能调用thread.sleep()方法,他有两个重载方法(sleep(int )、sleep(timespan)),只不过是表示时间量的格式不同而已,当在某线程内调用此函数时,他表示此线程将阻塞一段时间(时间是由传递给sleep 的毫秒数或timespan决定的,但若参数为0则表示挂起此线程以使其他线程能够执行,指定 infinite 以无限期阻塞线程),此时他的threadstate将变为waitsleepjoin,另外值得注意一点的是sleep()函数被定义为了static?! 这也意味着他不能和某个线程实例结合起来用,也即不存在类似于t1.sleep(10)的调用!正是如此,sleep()函数只能由需“sleep”的线程自己调用,不允许其他线程调用,正如when to sleep是个人私事不能由他人决定。不过当某线程处于waitsleepjoin状态而又不得不唤醒他时,可使用thread.interrupt方法 ,他将在线程上引发threadinterruptedexception。

1, ms不推荐通过thread state这个属性来同步线程,msdn原话:

 重要事项

只在几个调试方案中涉及线程状态。始终不应在代码中使用线程状态来同步线程活动。

以前我就看到了这句话,但不太明白,今天的深入调试,才发现确实如此,必须要始终注意,cpu的时间片是不可控且不可预知的,所以你也不知道你现在线程的状态是不是一定如你预料,比如

this._thread.ThreadState==ThreadState.running  很可能就不是你要的结果,可能线程的资源被抢占,现在处于watersleepjoin状态, 那么这句话返回的就是false了。


转载于:https://www.cnblogs.com/suijing/archive/2013/03/07/3379393.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很好的C#培训教程,适合初学者使用 目 录 1 .NET体系结构 7 1.1 什么是.NET Framwork? 7 1.2 .NET Framework的内容 7 1.3 如何用.NET Framework编写应用程序 8 1.4 MSIL和JIT 8 1.5 程序集 9 1.6 托管代码 9 1.7 垃圾回收 9 1.8 链接 10 1.9 实例分析 11 1.10 内容总结 13 1.11 独立实践 14 2 C#基础 15 2.1 面向对象基本概念 15 2.2 变量 18 2.3 常量 22 2.4 预定义数据类型 22 2.5 流控制 28 2.6 数组 37 2.7 命名空间 38 2.8 C#预处理器指令 44 2.9 C#编程规则 46 2.10 内容总结 50 2.11 独立实践 50 3 对象和结构 52 3.1 类和结构 52 3.2 类和成员 53 3.3 构造函数 60 3.4 结构 65 3.5 部分类 68 3.6 内容总结 72 3.7 独立实践 72 4 继承 73 4.1 继承的类型 73 4.2 结构和类 75 4.3 调用函数的基类版本 76 4.4 抽象类和抽象函数 77 4.5 密封类和密封方法 79 4.6 修饰符 80 4.7 接口 81 4.8 内容总结 86 4.9 独立实践 86 5 委托与事件 88 5.1 事件的原理 88 5.2 简单的自定义事件 89 5.3 预定义事件处理机制 92 5.4 内容总结 100 5.5 独立实践 100 6 运算符和类型强制转换 101 6.1 运算符 101 6.2 运算符的简化操作 102 6.3 类型的安全性 107 6.4 类型转换 108 6.5 装箱和拆箱 111 6.6 对象的相等比较 112 6.7 引用类型的相等比较 112 6.8 运算符重载 114 6.9 运算符的工作方式 114 6.10 用户定义的数据类型转换 118 6.11 执行用户定义的类型转换 119 6.12 多重数据类型转换 126 6.13 内容总结 130 6.14 独立实践 131 7 字符串与正则表达式 132 7.1 System.String类 132 7.2 StringBuilder成员 135 7.3 字符串的格式化 138 7.4 正则表达式概述 142 7.5 内容总结 149 7.6 独立实践 150 8 集合 151 8.1 集合 151 8.2 索引器 152 8.3 集合接口 155 8.4 字典 157 8.4.1 现实生活中的字典 158 8.4.2 .NET中的字典 158 8.4.3 字典的工作情况 160 8.5 内容总结 167 8.6 独立实践 167 9 错误与异常 168 9.1 错误和异常 168 9.2 捕获异常 170 9.3 System.Exception属性 177 9.4 嵌套的 try块 178 9.5 用户定义的异常类 180 9.6 内容总结 189 9.7 独立实践 189 10 内存管理与指针 190 10.1 后台内存管理 190 10.2 值数据类型 190 10.3 引用数据类型 192 10.4 垃圾收集 194 10.5 释放未托管的资源 195 10.6 析构函数 195 10.7 IDisposable接口 196 10.8 实现IDisposable接口和析构函数 198 10.9 不安全的代码 199 10.10 指针 200 10.11 使用指针优化性能 213 10.12 内容总结 217 11 泛型 218 11.1 泛型的概念 218 11.2 使用泛型 219 11.3 可空类型 219 11.4 运算符和可空类型 220 11.5 System.Collections.Generic命名空间 227 11.6 定义泛型类 237 11.7 default关键字 239 11.8 约束类型 240 11.9 从泛型类中继承 247 11.10 泛型运算符 248 11.11 泛型结构 250 11.12 定义泛型接口 250 11.13 定义泛型方法 251 11.14 定义泛型委托 253 11.15 独立实践 253 12 反射 254 12.1 定制特性 254 12.2 编写定制特性 255 12.3 指定特性参数 258 12.4 VectorClass程序集 261 12.5 反射 263 12.6 查找定制特性 269 12.7 内容总结 273 13 线程 274 13.1 线程 274 13.2 多线程应用程序 275 13.3 线程的处理 276 13.4 线程的优先级 282 13.5 同步 283 13.6 同步问题 285 13.7 内容总结 288 14 Winform基本概念 289 14.1 .NET Windows应用程序开发 289 14.2 .NET框架类库简介 289 14.3 事件和事件处理程序 290 14.4 事件参数 290 14.5 Windows 应用程序 290 14.6 窗体属性、方法和事件 291 14.7 this 关键字 292 14.8 控件概念 292 14.9 各种类型控件 292 14.10 控件的一些通用属性 294 14.11 标签、文本框、按钮控件简介 295 14.12 列表框控件简介 296 14.13 复选列表框 296 14.14 组合框 296 14.15 内容总结 302 15 Winform控件 303 15.1 控件分类 303 15.2 在窗体之间建立链接 307 15.3 应用程序的启动和关闭 308 15.4 内容总结 308 16 高级用户界面 309 16.1 打印控件的使用 309 16.2 PrintDocument组件 309 16.3 PrintPreviewControl组件 310 16.4 PrintDialog 组件 310 16.5 PrintPreviewDialog组件 311 16.6 PageSetUpDialog控件 311 16.7 对话框 311 16.8 通用对话框 312 16.9 OpenFileDialog控件 312 16.10 SaveFileDialog控件 312 16.11 FontDialog控件 312 16.12 ColorDialog控件 312 16.13 MessageBox消息框 313 16.14 WinForms 中的可视效果 314 16.15 内容总结 315 17 MDI应用程序 316 17.1 SDI程序 316 17.2 MDI程序 316 17.3 MenuStrip和ToolStripMenuItem 317 17.4 toolStrip控件简介 318 17.5 StatusStrip控件 320 17.6 创建对话框 320 17.7 内容总结 321 18 ADO.NET编程 322 18.1 简介 322 18.2 ADO.NET 的优点 322 18.3 ADO.NET 结构 324 18.4 ADO.NET 的基本组件 325 18.5 DataReader 328 18.6 获取单个值 328 18.7 修改数据库中的数据 329 18.8 从SQL Server获取XML数据 329 18.9 DataAdapter 330 18.10 数据集:DataSet 330 18.11 DataTable 330 18.12 DataView 332 18.13 关系 332 18.14 数据绑定 333 18.15 DataRow 简介 335 18.16 操纵数据源中的值 336 18.17 内容总结 336 19 GDI+ 编程 337 19.1 理解绘图规则 337 19.2 测量坐标和区域 341 19.3 绘制可滚动的窗口 343 19.4 颜色 348 19.5 画笔和钢笔 351 19.6 绘制图形和线条 352 19.7 显示图像 355 19.8 绘制文本 357 19.9 字体和字体系列 359 19.10 内容总结 363 20 自定义控件 364 20.1 添加事件处理程序 368 20.2 添加更多的属性 370 20.3 内容总结 372 21 部署与安装 373 21.1 部署的设计 373 21.2 无干涉部署 387 21.3 内容总结 394 22 ASP.NET与Web窗口简介 395 22.1 应用程序方案 395 22.2 Web 应用程序开发周期 399 五个对象实现了服务器端的请求 403 22.3 ASP.NET 的演变 404 22.4 Global.asax 文件 405 22.5 发布网站 408 22.6 内容总结 408 23 ASP.NET中的内置对象 409 23.1 ASP.NET页面 409 23.2 虚拟目录 421 23.3 内容总结 423 24 Web服务器控件 424 24.1 Web 控件 424 24.2 复杂控件 429 24.3 内容总结 431 25 HTML控件 432 25.1 服务器控件 432 25.2 HTMLForm控件 432 25.3 Web服务器控件优缺点 433 25.4 HTML服务器控件优缺点 433 25.5 使用服务器控件设计页面建议 433 25.6 内容总结 439 26 深入服务器对象 440 26.1 Global.asax文件简介 441 26.2 Application 对象 446 26.3 HttpServerUtility类和Server对象 446 26.4 HttpSessionState类和Session对象 448 26.5 内容总结 449 27 ADO.NET WEB应用 450 27.1 回顾ADO.NET 450 27.2 模板概念 464 27.3 ASP.NET 中的数据处理 465 27.4 内容总结 466 28 WEB服务器基础 467 28.1 ASP.NET Web 服务 467 28.2 编写简单的 Web 服务 468 28.3 内容总结 470 28.4 独立实践 470 29 用户控件 471 29.1 用户控件开发 471 29.2 内容总结 479 29.3 独立实践 480 30 Web部署 481 30.1 使用XCOPY部署 481 30.2 使用Visual studio的Copy Web Site功能部署 482 30.3 使用Visual Studio的Precompilation预编译部署 482 30.4 内容总结 483 30.5 独立实践 484

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值