摘要:
前两篇博客,分别介绍了用户模式和内核模式的同步构造,由于它们各有优势和劣势。本文将介绍如何将这两者的优势结合在一起,构建一个性能良好的同步机制。一,实现一个简单的混合同步锁#region hybird lock/// /// 简单的混合同步锁/// private sealed class Hybi... 阅读全文
随笔档案-2012年08月
基元线程同步——内核模式构造(WaitHandle,EventWaitHandle,AutoResetEvent,ManualResetEvent,Semaphore,Mutex)
2012-08-29 17:46 by xiashengwang, 2823 阅读, 收藏, 编辑
摘要:
一、内核模式构造内核模式构造,采用的是windows操作系统来同步线程,比VolatileRead,VolatileWrite,Interlocked等用户模式的构造慢很多。相对于用户模式的构造,它也有自己的优点:1,不用像用户模式那样占着cpu“自旋”,浪费cpu资源。2,内核模式可同步在同一机器不同进程中运行的线程。3,可实现本地和托管线程相互之间的同步。4,一个线程可以一直阻塞,直到一个集合中的内核对象全部可用,或部分可用。(WaitAll,WaitAny)5,阻塞一个线程时,可以指定一个超时值,超过这个时间就解除阻塞。二、FCL提供的内核模式构造层次结构WaitHandle(抽象类) 阅读全文
基元线程同步——Interlocked Anything模式
2012-08-29 14:19 by xiashengwang, 971 阅读, 收藏, 编辑
摘要:
上一篇基元线程同步——基础,非阻塞同步(VolatileRead,VolatileWrite,volatile,Interlocked)已经对Interlocked类做了比较详细的分析,这一篇是对Interlocked类的一个模式进行补充说明。如果没用过Interlocked类,可以看看上面的这篇文章。这个模式的名字是Jeffrey给起的,它究竟要解决什么问题,我们为什么要用它?带着这些疑问,我们来看看它的应用场景。看看下面这个设定最大值的例子: private static Int32 Maximum(ref int target, int value) { ... 阅读全文
基元线程同步——基础,非阻塞同步(VolatileRead,VolatileWrite,volatile,Interlocked)
2012-08-25 11:22 by xiashengwang, 4041 阅读, 收藏, 编辑
摘要:
一、基元用户模式和内核模式。基元(Primitive):指代码中可以使用的最简单的构造。有两种基元构造:用户模式(user-mode)和内核模式(kernel-mode)。1,用户模式。它是用CPU指令来协调线程,这种协调是在硬件中发生的,所以速度会快于内核模式。但是也意味着,Windows操作系统永远也检测不到一个线程在一个基元用户模式构造上阻塞了。由于在一个基元用户模式构造上阻塞的线程永远不认为已经阻塞,所以线程池不会创建新的线程来替换这种阻塞的线程。另外,这些CPU指令只是阻塞线程极短的时间。缺点:只有Windows系统的内核才能停止一个线程的执行。用户模式中的线程可能会被系统抢占,但很 阅读全文
线程同步——优势、劣势
2012-08-25 10:16 by xiashengwang, 824 阅读, 收藏, 编辑
摘要:
一、线程同步好处:多个线程同时访问共享数据时,防止数据被损坏。二、线程同步带来的问题:1,实现比较繁琐,而且容易出错。必须对多个线程可能同时访问的所有数据,用额外的代码包围起来,以获得和释放一个同步锁。这需要由程序员来保证没有遗漏,对多线程共享的数据的加锁工作。并且,在程序完成时,需要进行压力测试以保证多个线程并发时,结果如预期。2,它会损害性能。获取和释放一个锁是需要时间的。因为需要额外的调用一些方法,并且需要协调调度下一个获得锁的线程。3,每次只能允许一个线程访问资源。这是锁的全部意义所在,但也是问题所在,因为阻塞一个线程可能会造成更多的线程被创建。三、线程同步建议:1,线程同步并不是一件 阅读全文
DataGridView的VirtualMode,在大容量数据加载时特别有用
2012-08-24 17:39 by xiashengwang, 7926 阅读, 收藏, 编辑
摘要:
DataGridView的虚拟模式,允许我们在需要时再检索数据。达到实时加载的目的。这避免了DataGridView由于大数据量而刷新延迟,也避免了数据量过大造成网络超时,更可以节约本地内存。总之,它的好处多多,但是要实现这种方式,需要做的事情可不是那么简单,所以需要权衡项目中是否有这样的大数据。 阅读全文
研究BackgroundWorker后发现:AsyncOperation和SynchronizationContext的差异真的很大!
2012-08-22 15:58 by xiashengwang, 1615 阅读, 收藏, 编辑
摘要:
今天研究BackgroundWorker代码时发现,两处代码的写法有些不一致,于是好奇的测试了一番,以为能测出BackgroundWorker的一个bug。结果大家都知道microsoft胜了。下面来看看过程,BackgroundWorker类里的ReportProgress方法public void ReportProgress(int percentProgress, object userState){if (!this.WorkerReportsProgress) throw new InvalidOperationException("BackgroundWorker_Wo 阅读全文
APM异步编程模型的优势
2012-08-21 14:11 by xiashengwang, 1279 阅读, 收藏, 编辑
摘要:
我们之所以要花大力气学习APM,就必须要清楚它能解决实际编程中的那些难题。以及现有的技术为什么不行。简单点说:APM是基于IAsyncResult接口的,采用的BeginXXX和EndXXX的形式来实现异步。下面这几点就是APM的优势:1,线程执行是异步的,不会阻塞调用线程。这一点也是我们使用异步的主要目的,我们不就是希望后台处理一些耗时操作吗?2,任务完成可以得到通知。(非阻塞)3,任务可以实现进度报告。(需要额外的辅助代码支持)4,可以有返回值。5,参数可以是多个。再看看Thread,ThreadPool,Task能实现上面的几点?这三个中,Task是相对完善的一个,对于第2点它可以通过C 阅读全文
定时器Timer的选择
2012-08-18 18:20 by xiashengwang, 520 阅读, 收藏, 编辑
摘要:
FCL提供了好几个Timer供我们选择,但却让很多人分不清他们的使用场合。下面来总结一下:System.Threading的Timer类。要在线程池上定时执行后台任务,他就是就好的选择。System.Windows.Forms的Timer类。这个类可以通过Vs的设计界面拖拽,它和UI线程是相关的,它使用的就是UI线程,所以在这里面执行UI更新的操作不会报线程非法访问的错。但是,如果在定时执行的函数里有长时间的运行任务,则会阻塞UI线程,造成界面”假死“。System.Windows.Threading的DispatcherTimer类。这个是System.Windows.Forms的Timer 阅读全文
线程阶段性总结——APM,ThreadPool,Task,TaskScheduler ,CancellationTokenSource
2012-08-18 16:39 by xiashengwang, 2460 阅读, 收藏, 编辑
摘要:
不管我们使用thread,threadPool,task,还是APM异步,本质都是在使用多线程。对于新手来说,不太敢用多线程的原因,就我个人的体验来说,就是对多线程的异常捕获方式或时机缺乏了解,而一旦出现异常没有捕获,将会带来难以发现的bug,进而造成系统崩溃。而多线程本身也不是一朝一夕就能学好的,必须不断的去学习总结,所以我个人认为你要用一种线程模型,首先要对它有足够的了解,特别是对异常的捕获。如果你没有完全的把握,最好在实际开发中谨慎的用多线程。1,APM异步编程模型。采用BeginXXX和EndXXX方法。关于异常的捕捉,对于刚调用BeginXXX抛出的异常,异步操作可能还没有进入队列。 阅读全文
非UI线程更新UI界面的各种方法小结
2012-08-18 15:58 by xiashengwang, 5520 阅读, 收藏, 编辑
摘要:
我们知道只有UI线程才能更新UI界面,其他线程访问UI控件被认为是非法的。但是我们在进行异步操作时,经常需要将异步执行的进度报告给用户,让用户知道任务的进度,不至于让用户误认为程序“死掉了”,特别是对于Winform,WPF等客户端程序尤为重要。 那么我们要探讨的就是如何让非UI的任务线程更新UI界 阅读全文
Linq学习之旅——Linq to Objects之立即执行方法(下篇)
2012-08-11 21:20 by xiashengwang, 557 阅读, 收藏, 编辑
摘要:
1,ElementAt 方法2,ElementAtOrDefault 方法3,All 方法4,Any 方法5,Contains 方法6,Count 方法7,LongCount 方法8,Aggregate 方法9,Sum 方法10,Average 方法11,Min 方法12,Max 方法1,ElementAt 方法获取序列中指定索引的元素,如果索引超过范围将引发异常。 private void ElementAtDemo() { string[] names = { "郭靖", "李莫愁", "欧阳晓晓", "黄蓉" 阅读全文
Linq学习之旅——Linq to Objects之立即执行方法(上篇)
2012-08-11 18:00 by xiashengwang, 580 阅读, 收藏, 编辑
摘要:
1,ToArray 方法2,ToList 方法3,ToDictionary 方法4,ToLookup 方法5,SequenceEqual 方法6,First 方法7,FirstOrDefault方法8,Last 方法9,LastOrDefault 方法10,Single 方法11,SingleOrDefault 方法1,ToArray 方法从IEnumerable<T>创建一个数组。 string[] names = { "郭靖", "李莫愁", "黄蓉", "黄药师" }; var query = f 阅读全文
颜色分段显示,线性填充的一个Demo
2012-08-02 17:51 by xiashengwang, 1751 阅读, 收藏, 编辑
摘要:
1,指定一个开始颜色,一个结束颜色,进行填充。2,生成指定数量的,这两个颜色中间的过渡色,这个对地图表示等功能需要分段颜色表示的很有用。效果图:先看第一个功能,填充渐变的颜色:主要就是利用LinearGradientBrush这个画刷 lblStartColor.Click += new EventHandler(lblColor_Click); lblEndColor.Click += new EventHandler(lblColor_Click); void lblColor_Click(object sender, EventA... 阅读全文
一个关于字典查找引发的思考——BinarySearch
2012-08-02 12:20 by xiashengwang, 1983 阅读, 收藏, 编辑
摘要:
最近在一个e文网站的提问区看到一个非常有意思的问题,内容如下:有几组信号范围(range),每个范围对应一个位置(Position):Signal Strenth Position0-9 110-19 220-29 3要求很简单,就是比如输入一个15,找到它的Position为2。但要求不能用IF语句进行简单的判定,最好用类似于字典的查找。看见这个问题,你脑海中有什么样的方案?Dictionary?在实际工作中还是经... 阅读全文
GC垃圾回收——有用的函数和类
2012-08-01 16:10 by xiashengwang, 5605 阅读, 收藏, 编辑
摘要:
1,AddMemoryPressure和RemoveMemoryPressure 这两个方法主要用于本地资源,比如一个位图占用了50M本地内存,但是托管对象只包含一个HBitMap(4字节或8字节)。但CRL并不知道这个内存压力,它可能允许你分配数百个位图,因为它们占用的托管内存太少了。这两个方法的目的就是要告诉GC它实际的本地资源用了多少内存量,GC知道这个信息后会调整它的垃圾回收策略,当压力变大时,他就强制执行垃圾回收。 private void MemoryPressureDemo(int size) { //创建一组对象,并指定它们的... 阅读全文