您的位置:首页 > 编程语言 > C#

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

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

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

多线程适合处理的任务性质多为耗时的等待,或轮询判断状态。而此数据管理系统的瓶颈却是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了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: