代码改变世界

随笔分类 - .net

对象锁感悟

2012-07-18 14:09 by 田志良, 2245 阅读, 收藏, 编辑
摘要:1、对于一个对象,读取对象元素无须加锁,增加、修改、删除、遍历须加锁。 2、如果对象a包含另外一个对象b,针对对象a的操作只要锁住对象a,针对对象b的操作只要锁住对象b。 3、如果对象a包含对象b,对象b包含对象c,对c的操作可以锁住c,可以锁住b,也可以锁住a,至于锁哪个,据具体的业务逻辑性能要求来定。 4、有时为了防止并发覆盖,可扩大锁范围。 阅读全文

反射调用性能比较(附源码)

2012-06-29 17:33 by 田志良, 5762 阅读, 收藏, 编辑
摘要:本文通过编写Demo,测试“传统反射”、“实例反射”、“快速反射”、“直接调用”的性能。 阅读全文

C#设计模式(外观模式)

2011-09-30 11:06 by 田志良, 3676 阅读, 收藏, 编辑
摘要:如果要观看电影,必须在客户端执行下面的操作:先打开投影仪,再打开功放机,再打开屏幕,再打开 DVD 播放机,再打开灯光,在经历了这么多操作后,才可以看一场电影。而在关闭电影的时候,也要先关闭投影仪,再关闭功放机,再关闭屏幕,再关闭 DVD 播放机,再关闭灯光。哦,这是太复杂了!!!在客户端居然有那么多操作,如果有一些用户不知道如何使用其中的一个工具,那他便看不了电影! 阅读全文

C#设计模式(适配器模式)

2011-09-29 16:50 by 田志良, 3794 阅读, 收藏, 编辑
摘要:众所周知,在中国通用的电压时 220V,而美国电压则是 110V,如果有经常在美国和中国之间跑的 IT 人,而其笔记本都是随身携带的,那么它的笔记本的电压问题如何解决呢?(因为在美国和中国电压不同,所以一般的电器会不通用的)而适配器在这个问题上体现得淋漓尽致。现在的笔记本都有一个电源适配器,而正是这个电源适配器来解决上面提到的适配器问题,比如,一款索尼笔记本,其输入电流为交流100V~240V,而输出则是统一的直流 19.5V,在电源适配器的一端输入交流电流,然后通过电源适配器把电源变成需要的电压,也就是适配器的作用是使得一个东西适合另外一个东西。 阅读全文

利用Anchor和Dock属性管理WinForm控件

2011-08-18 15:39 by 田志良, 1085 阅读, 收藏, 编辑
摘要:有一点让许多刚接触WinForms编程的开发者感到很棘手,就是在用户调整各种控件的大小时,怎样使它们的窗体保持同步,并与父窗体相称。这可以成为一种让人非常沮丧的情况,尤其是对于有着Web编程背景,转为WinForms的开发者来说。为了缓解这个问题,.NET框架允许你对子控件设置属性,命令在调整父窗体大小时,它们应该如何运作。用来命令控件在调整大小时动作的两个属性就是“Dock”和“Anchor”。Dock和Anchor通过将控件连接到它们父窗体的某个位置,而免除了使应用程序具有不可预知界面的麻烦。最好的一点就是设立这些属性不需要任何手写代码。所有事情都可以通过Visual Studio IDE中的点和单击来完成。 阅读全文

C#控件前缀名大全

2011-08-17 09:07 by 田志良, 1428 阅读, 收藏, 编辑
摘要:标准控件 1 btn Button 2 chk CheckBox 3 ckl CheckedListBox 4 cmb ComboBox 5 dtp DateTimePicker 6 lbl Label 7 llb LinkLabel 8 lst ListBox 9 lvw ListView 10 mtx MaskedTextBox 11 cdr MonthCalendar 12 icn NotifyIcon 13 nud NumeircUpDown 14 pic PictureBox 15 prg ProgressBar 16 rdo RadioButton 17 rtx RichTextBox 18 txt TextBox 19 tip ToolTip 20 tvw TreeView 21 wbs WebBrowser 阅读全文

WCF SOAP消息剖析

2011-07-22 16:06 by 田志良, 3361 阅读, 收藏, 编辑
摘要:小时候,我们学习到邮票应该贴在信封的右上角,地址应该写在中间。如果我们愿意,可以增加一个回复地址在信封的左上角。所有被处理的信件必须遵守这个基本的结构。如果格式不对,或者地址不清晰,或者地址不合法,邮政服务会认为这个邮件无效,并且无法投递。如果我们幸运的话,邮件会被退回(如果写地址的话)。可以想象没写地址有多混乱。如果发送者可以允许乱放邮票或者地址,邮政服务需要查遍整个信封来确定邮票和地址。很可能,为了完成新加投递任务,每次可能要增加远多于2美分的邮资。实际上,邮局定义的信封结构,从发信人角度来看,会改进信件处理的效率和一致性而不需要牺牲可用性。 阅读全文

WCF消息参与者

2011-07-22 15:36 by 田志良, 641 阅读, 收藏, 编辑
摘要:在面向服务的应用中,消息是通信的基本单位。因此,面向服务的应用通常被称为消息应用系统。在某一时刻,每个面向服务的应用系统都会发送或者接受消息。这个能够帮助你理解面向服务的消息很像你在Email系统里收到的信件一样。在邮件系统里,一个信件是抽象的实体:它可以包涵任何类型的信息,可以以不同的形式和大小存在,可以关联任何东西。同样,一个面向服务的消息也是一个抽象实体:它几乎可以包涵任何数据,可以使用许多不同的方式编码,并且可以关联到虚拟东西,甚至是其它消息。邮件的一些属性已经被广泛接受。例如,一封信件可以被某个人发送,邮寄给某个人,并且可能被某个人投递(某一时刻更多的是“可能”)。同样,一个面向服务的消息可以被计算机发送,发送给另一个计算机,并且可能由另外的计算机来投递。考虑某些喜欢死扣理论的书呆子,我必须澄清,与面向服务消息交互的实体不一定必须是计算机。理论上说,它们可以是信鸽,拉布拉多猎犬或者是狮虎。无论如何,这些与面向服务消息交互的实体被称作消息的参与者,并且在这本书里,一个消息参与者可以是一个计算机上的进程。 阅读全文

C#实现动态生成Word

2011-07-07 10:14 by 田志良, 10377 阅读, 收藏, 编辑
摘要:本篇文章主要介绍一个控制台例子,实现动态生成Word文件。 阅读全文

怎样编写注册表reg文件

2011-07-06 17:03 by 田志良, 1973 阅读, 收藏, 编辑
摘要:1、开头第一行一定是:“REGEDIT4”或“Windows Registry Editor Version 5.00”,以区别操作系统; 2、注册表信息头尾用“[”与“]”包起来; 3、" "内就是字符串内容; 4、“DWORD”为“0”就是用“dword:00000000”表示,因为“DWORD”值是16进位,16进位的“0”就是“00000000”。 5、因为本例中只有一行注册表信息([HKEY_CURRENT_USER\Software\Mi...]),所以没有空行。而如果有两个以上的注册表信息,信息与信息之间就需要有空行隔开。 6、如果要删除某个注册表信息该怎么办?很简单,在注册表信息前面加上“-”(减)号 阅读全文

C#线程优先级详解

2011-03-07 17:14 by 田志良, 13924 阅读, 收藏, 编辑
摘要:计算机中经常会有多个任务同时运行,其中总有一些看起来更紧急,更需要优先完成。比如我们现在有两个任务,一个任务是下载一部电影,另一个任务是检测用户的输入。显然及时响应用户操作应具有更高的优先级,因为我们不能让用户等得太久。 阅读全文

.net垃圾回收机制详解

2011-03-06 23:01 by 田志良, 1459 阅读, 收藏, 编辑
摘要:作为一个.NET程序员,我们知道托管代码的内存管理是自动的。.NET可以保证我们的托管程序在结束时全部释放,这为我们编程人员省去了不少麻烦,我们可以连想都不想怎么去管理内存,反正.NET自己会保证一切。好吧,有道理,有一定的道理。问题是,当我们用到非托管资源时.NET就不能自动管理了。这是因为非托管代码不受CLR(Common Language Runtime)控制,超出CLR的管理范围。那么如何处理这些非托管资源呢,.NET又是如何管理并释放托管资源的呢? 阅读全文

IDisposable接口详解

2011-03-04 19:52 by 田志良, 4846 阅读, 收藏, 编辑
摘要:本文详细介绍IDisposable在回收资源的应用。 阅读全文

ManualResetEvent详解

2011-03-04 11:25 by 田志良, 31645 阅读, 收藏, 编辑
摘要:本文着重讲解ManualResetEvent如何实现线程同步,并附源代码哦。 阅读全文

c#前台线程与后台线程的区别和联系

2011-03-03 16:16 by 田志良, 17226 阅读, 收藏, 编辑
摘要:.net环境使用Thread建立的线程默认情况下是前台线程,即线程属性IsBackground=false,在进程中,只要有一个前台线程未退出,进程就不会终止。主线程就是一个前台线程。而后台线程不管线程是否结束,只要所有的前台线程都退出(包括正常退出和异常退出)后,进程就会自动终止。 阅读全文

通用守护进程的实现

2011-02-12 11:55 by 田志良, 21999 阅读, 收藏, 编辑
摘要:用户指定要守护的应用程序(数量不限),该应用程序不仅包括exe可执行文件,还包括诸如jpg、txt等所有能双击打开执行的应用程序。用户设定好要守护的应用程序后,关闭应用程序(包括合法和非法关闭),该应用程序要能立即重启打开。当电脑重启时,要守护的应用程序也能自动全部打开。 阅读全文

远程应用程序域通信 MarshalByRefObject

2011-01-07 13:49 by 田志良, 1850 阅读, 收藏, 编辑
摘要:应用程序域是一个操作系统进程中一个或多个应用程序所驻留的分区。同一应用程序域中的对象直接通信。不同应用程序域中的对象的通信方式有两种:一种是跨应用程序域边界传输对象副本,一种是使用代理交换消息。MarshalByRefObject 就是通过使用代理交换消息来跨应用程序域边界进行通信的对象的基类。 阅读全文

delegate,event, lambda,Func,Action以及Predicate

2011-01-06 15:56 by 田志良, 3342 阅读, 收藏, 编辑
摘要:1. delegate 委托 可以理解为cxx 语言中的函数指针,标示了方法调用的回调函数的规范。强类型,便于编译时检查是它的最大优点,从此可以和void * 说再见了。 2. event 事件 用以delegate委托声明事件,标示响应该事件的回调函数必须符合其声明委托的定义 3. lambda 表达式 在.net世界中表现为匿名委托,之前又要提到匿名方法(函数) 阅读全文

Lambda 表达式 和 Predicate 泛型委托

2011-01-06 14:36 by 田志良, 6333 阅读, 收藏, 编辑
摘要:“Lambda 表达式”是一个匿名函数,用于创建委托或表达式树类型。 “=>”为Lambda 运算符,读为“goes to”。Lambda 运算符左边是“输入参数”,右边是“表达式或语句块”,如下所示: delegate int del(int i); static void Main(string[] args) { del myDelegate = x => x * x; int j = myDelegate(5); //j = 25 } 阅读全文

浅析Base64

2010-12-01 17:31 by 田志良, 820 阅读, 收藏, 编辑
摘要:按照RFC2045的定义,Base64被定义为:Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式。(The Base64 Content-Transfer-Encoding is designed to represent arbitrary sequences of octets in a form that need not be humanly readable.) 阅读全文

ASCII,Unicode和UTF-8之间的区别和联系

2010-12-01 16:20 by 田志良, 995 阅读, 收藏, 编辑
摘要:我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串。每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte)。也就是说,一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从0000000到11111111。 上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定。这被称为ASCII码,一直沿用至今。 ASCII码一共规定了128个字符的编码,比如空格“SPACE”是32(二进制00100000),大写的字母A是65(二进制01000001)。这128个符号(包括32个不能打印出来的控制符号),只占用了一个字节的后面7位,最前面的1位统一规定为0。 阅读全文

如何避免System.OutOfMemonryException异常

2010-11-03 14:27 by 田志良, 1586 阅读, 收藏, 编辑
摘要:在什么情况下会出现OutOfMemonryException呢?第一种情况:在试图新建一个对象时,垃圾收集器找不到任何可用内存,会抛出该异常,这种情况,我们是可以捕获该异常的;另一种情况是:CLR需要内存,而系统却不能提供,也会抛出该异常, 但此时,应用程序不能捕获该异常。 阅读全文

Try-Catch机制使用场景分析

2010-10-09 15:37 by 田志良, 3116 阅读, 收藏, 编辑
摘要:在什么场景下加Try-Catch机制 1)以业务逻辑功能为单位,在最上层加Try-Catch机制。为什么要这样做呢?这主要是增加程序的健壮性,防止因抛出异常过多,导致程序崩溃。 2)底层代码,在可能出错的地方加Try-Catch机制,用Catch侦测具体的异常,然后就具体的异常,采取相应的解决方案。 3)底层代码,在需异常追踪时加Try-Catch机制,在Catch块中抛出自定义异常,调试时可迅速定位到错误代码段。 阅读全文

浅析 c# Queue

2010-09-21 16:02 by 田志良, 22726 阅读, 收藏, 编辑
摘要:1、Queue 的容量是 Queue 可以保存的元素数。Queue 的默认初始容量为 32。向 Queue 添加元素时,将通过重新分配来根据需要自动增大容量。可通过调用 TrimToSize 来减少容量。等比因子是当需要更大容量时当前容量要乘以的数字。在构造 Queue 时确定增长因子。默认增长因子为 2.0。 2、Queue 能接受空引用作为有效值,并且允许重复的元素。 3、空引用可以作为值添加到 Queue。若要区分空值和 Queue 结尾,请检查 Count 属性或捕捉 Queue 为空时引发的 InvalidOperationException异常。 阅读全文

深入理解堆栈、堆在内存中的实现

2010-09-19 09:46 by 田志良, 19285 阅读, 收藏, 编辑
摘要:尽管在.NET framework下我们并不需要担心内存管理和垃圾回收(GarbageCollection),但是我们还是应该了解它们,以优化我们的应用程序。同时,还需要具备一些基础的内存管理工作机制的知识,这样能够有助于解释我们日常程序编写中的变量的行为。在本文中我将讲解栈和堆的基本知识,变量类型以及为什么一些变量能够按照它们自己的方式工作。 在.NET framework环境下,当我们的代码执行时,内存中有两个地方用来存储这些代码。假如你不曾了解,那就让我来给你介绍栈(Stack)和堆(Heap)。栈和堆都用来帮助我们运行代码的,它们驻留在机器内存中,且包含所有代码执行所需要的信息。 阅读全文

c# 多线程 --Mutex(互斥锁)

2010-09-01 14:17 by 田志良, 8837 阅读, 收藏, 编辑
摘要:互斥锁(Mutex) 互斥锁是一个互斥的同步对象,意味着同一时间有且仅有一个线程可以获取它。 互斥锁可适用于一个共享资源每次只能被一个线程访问的情况 函数: //创建一个处于未获取状态的互斥锁 Public Mutex(); //如果owned为true,互斥锁的初始状态就是被主线程所获取,否则处于未获取状态 Public Mutex(bool owned); 如果要获取一个互斥锁。应调用互斥锁上的WaitOne()方法,该方法继承于Thread.WaitHandle类 它处于等到状态直至所调用互斥锁可以被获取,因此该方法将组织住主调线程直到指定的互斥锁可用,如果不需要拥有互斥锁,用ReleaseMutex方法释放,从而使互斥锁可以被另外一个线程所获取。 阅读全文

c# Stack操作类

2010-09-01 08:35 by 田志良, 7157 阅读, 收藏, 编辑
摘要:Stack类代码: using System; //using System.Collections.Generic; using System.Text; using System.Collections; namespace StackHelper { class StackHelper { private Stack list; public Stack List { set { list = value; } get { return list; } } public StackHelper() { list = new Stack();//注意:不是list=new StackHelper() Console.WriteLine("---------Stack-----------"); } 阅读全文

c#实现每隔一段时间执行代码(多线程)

2010-08-31 17:53 by 田志良, 53941 阅读, 收藏, 编辑
摘要:总结以下三种方法,实现c#每隔一段时间执行代码: 方法一:调用线程执行方法,在方法中实现死循环,每个循环Sleep设定时间; 方法二:使用System.Timers.Timer类; 方法三:使用System.Threading.Timer; 阅读全文

c# Semaphore(信号量)

2010-08-31 14:18 by 田志良, 18595 阅读, 收藏, 编辑
摘要:信号量 Semaphore 类似互斥锁,但它可以允许多个线程同时访问一个共享资源 通过使用一个计数器来控制对共享资源的访问,如果计数器大于0,就允许访问,如果等于0,就拒绝访问。计数器累计的是“许可证”的数目,为了访问某个资源。线程必须从信号量获取一个许可证。 通常在使用信号量时,希望访问共享资源的线程将尝试获取一个许可证,如果信号量的计数器大于0,线程将获取一个许可证并将信号量的计数器减1,否则先线程将阻塞,直到获取一个许可证;当线程不再需要共享资源时,将释放锁拥有的许可证,并将许可证的数量加1,如果有其他的线程正在等待许可证,那么该线程将立刻获取许可证。 另外,允许同时访问的资源的进程数量是在创建信号量时指定的,如果创建一个允许进程访问的信号量数目为1,则该信号量就和互斥锁的用法一样。 Public Semaphore(int initialCount,int maximumCount) initialCount指信号量许可证的初始值,maximumCount为最大值 获取许可证使用WaitOne() 不需要时释放使用 public 阅读全文

C#中异步和多线程的区别

2010-08-31 14:15 by 田志良, 14349 阅读, 收藏, 编辑
摘要:C#中异步和多线程的区别是什么呢?异步和多线程两者都可以达到避免调用线程阻塞的目的,从而提高软件的可响应性。甚至有些时候我们就认为异步和多线程是等同的概念。但是,异步和多线程还是有一些区别的。而这些区别造成了使用异步和多线程的时机的区别。 异步和多线程的区别之异步操作的本质 所有的程序最终都会由计算机硬件来执行,所以为了更好的理解异步操作的本质,我们有必要了解一下它的硬件基础。 熟悉电脑硬件的朋友肯定对DMA这个词不陌生,硬盘、光驱的技术规格中都有明确DMA的模式指标,其实网卡、声卡、显卡也是有DMA功能的。DMA就是直 接内存访问的意思,也就是说,拥有DMA功能的硬件在和内存进行数据交换的时候可以不消耗CPU资源。只要CPU在发起数据传输时发送一个指令,硬件就开 始自己和内存交换数据,在传输完成之后硬件会触发一个中断来通知操作完成。这些无须消耗CPU时间的I/O操作正是异步操作的硬件基础。所以即使在DOS 这样的单进程(而且无线程概念)系统中也同样可以发起异步的DMA操作。 异步和多线程的区别之线程的本质 线程不是一个计算机硬件的功能,而是操作系统提供的一种逻 阅读全文

c# Buffer学习笔记

2010-08-31 14:09 by 田志良, 8631 阅读, 收藏, 编辑
摘要:System.Buffer 以字节数组(byte[])方式操作基元类型数组,相当于 C 语言的 (char*)int_pointer 指针操作。 1. Buffer.ByteLength 该方法范围基元类型数组累计有多少字节组成。 var bytes = new byte[] { 1, 2, 3 }; var shorts = new short[] { 1, 2, 3 }; var ints = new int[] { 1, 2, 3 }; Console.WriteLine(Buffer.ByteLength(bytes)); // 1 byte * 3 elements = 3 Console.WriteLine(Buffer.ByteLength(shorts)); // 2 byte * 3 elements = 6 Console.WriteLine(Buffer.ByteLength(ints)); // 4 byte * 3 elements = 12 也就是说该方法结果等于"基元类型字节长度 * 数组长度" 。 2. 阅读全文

深入理解静态方法和实例化方法

2010-08-31 14:02 by 田志良, 804 阅读, 收藏, 编辑
摘要:静态方法和实例化方法的区别,这是一个经常被时时提出来的问题,很多时候我们以为理解了、懂了,但深究一下,我们却发现并不懂。 方法是我们每天都在写得,很多程序员大多都使用实例化方法,而很少使用静态方法,问原因也说不出来所以然,或者简单的回答两者定义的区别,静态方法不需要new就可以使用 实例化方法需要new了以后才可以使用。。。。我们真的理解了吗? 从实际项目开发说起,这里有开发项目的三种方式: 开发项目中把BLL和DAL分开,在BLL调用DAL的代码。 一、在DAL中使用静态方法,不创建实例直接调用(大概有很多人都使用这种方式开发 ) class DAL { public static string GetUserName(...); } 在BLL中调用: DAL.GetUserName(); 二、在DAL中使用实例方法,采用静态成员模式(或Singleton)通过实例来调用: class DAL { public static readonly DAL dal = new DAL(); public string GetUserName(... 阅读全文

深入理解c#中的lock

2010-08-26 22:32 by 田志良, 729 阅读, 收藏, 编辑
摘要:lock只能使用引用类型,严格来说是需要对象的实例。即使对象在意义上是相同的,但是如果不是ReferenceEquals的话,那么将作为两个实例来对待,那么C# lock 的就不是同一个东西。也就是说,当你以为这个 lock 生效的话,它其实在做无用工。 阅读全文

c#多线程调用有参数的方法

2010-08-25 23:06 by 田志良, 2315 阅读, 收藏, 编辑
摘要:将线程要执行的方法参数封装到类里面,通过实例化该类,初始化方法参数,这样就实现多线程用无参的方式调用有参的方法。 阅读全文

c#正则表达式使用详解

2010-08-25 22:48 by 田志良, 492 阅读, 收藏, 编辑
摘要:正则表达式(Regular expressions)是一套语法匹配规则,各种语言,如Perl, .Net和Java都有其对应的共享的正则表达式类库。在.Net中,这个类库叫做Regex。简单的说,Regex是从字符窗中查找匹配字符串的应用类。通过Regex,编程人员能够非常方便的从一段数据中提取自己所需要的数据信息。 Regex的构造函数有三种,在这里就不讨论默认构造函数了。另外两个构造函数中,一个构造函数接收正则表达式字符串作为入参,另一个以正则表达式字符串和RegexOptions作为入参。如: Regex regex = new Regex("w+$"); Regex regex = new Regex("s+", RegexOptions.IgnoreCase | RegexOptions.Multiline); RegexOptions可以为我们提供一些特殊的帮助,比如IgnoreCase能够在匹配是忽略大小写,Multiline能够调整^和$的意义,改为匹配一行的开头和结尾。 Regex有两个获取匹配的方法Match()和Matches(),分别代表匹配一个,匹配 阅读全文

c#线程池详解

2010-08-25 09:04 by 田志良, 4183 阅读, 收藏, 编辑
摘要:当 CLR 初始化时,其线程池中不含有线程。当应用程序要创建线程来执行任务时,该应用程序应请求线程池线程来执行任务。线程池知道后将创建一个初始线程。该新线程经历的初始化和其他线程一样;但是任务完成后,该线程不会自行销毁。相反,它会以挂起状态返回线程池。如果应用程序再次向线程池发出请求,那么这个挂起的线程将激活并执行任务,而不会创建新线程。这节约了很多开销。只要线程池中应用程序任务的排队速度低于一个线程处理每项任务的速度,那么就可以反复重用同一线程,从而在应用程序生存期内节约大量开销。 那么,如果线程池中应用程序任务排队的速度超过一个线程处理任务的速度,则线程池将创建额外的线程。当然,创建新线程确实会产生额外开销,但应用程序在其生存期中很可能只请求几个线程来处理交给它的所有任务。因此,总体来说,通过使用线程池可以提高应用程序的性能。线程池的一个绝妙特性是:它是启发式的。如果您的应用程序需要执行很多任务,那么线程池将创建更多的线程。如果您的应用程序的工作负载逐渐减少,那么线程池线程将自行终止。线程池的算法确保它仅包含置于其上的工作负荷所需要的线程数! 阅读全文