自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(32)
  • 收藏
  • 关注

原创 反射的性能

反射是相当强大的一个机制,它允许在运行时发现并使用编译时还补了解的类型或成员。但是,它有下面两个缺点。1,反射会造成编译时无法保证类型类型安全性。由于反射要严重依赖字符串,所以会丧失编译时的类型安全性。2,反射速度慢。使用反射时,类型或成员的名称在编译时未知;要用字符串名称标识每个类型及其成员,以便在运行时发现他们。也就是说,使用System.Reflection命名空间中的类型扫描程序集的元数据时,反射要不断地执行字符串搜索。通常,字符串搜索执行的是不区分大小写的比较,这会进一步影响速度。使用反射调

2020-12-13 20:29:43 1254

原创 程序集加载

JIT编译器将方法的IL代码编译成本地代码时,会查看IL代码中引用了哪些类型。在运行时,JIT编译器利用程序集的TypeRef和AssemblyRef元数据表来确定哪一个程序集定义了所引用的类型。在AssemblyRef元数据表的记录项中,包含了构成程序集强名称的各个部分。JIT编译器所获取所有这些部分——包括名称(无扩展名和路径)、版本、语言文化和公钥标记(public key token)——并把他们连接成一个字符串。然后,JIT编译器尝试将与该标识匹配的一个程序集加载到AppDomain中(如果还没有

2020-12-08 22:13:43 243

原创 .net AppDomain

CLR COM服务器初始化,会创建一个AppDomain 。 AppDomain是一组程序集的逻辑容器。CLR初始化时创建的第一个AppDomain称为默认AppDomain, 这个默认的AppDomain只有在Windows进程终止时才会被销毁。除了默认AppDomain, 正在使用非托管COM接口方法或托管类型方法的一个宿主还可指示CLR创建额外的AppDomain。 AppDomain唯一的作用就是进行隔离。下面总结了AppDomain的具体功能。1,一个AppDomain中的代码创建的对象不能由

2020-11-29 23:04:50 140

原创 .net 线程协作式取消

.net framework 提供了一个标准的取消操作模式。这个模式是协作式的,意味着你想取消的操作必须显式地支持取消。换言之,无论执行操作的代码,还是试图取消操作的代码,都必须使用本节提到的类型。对于长时间运行的计算限制操作来说,支持取消是一件很“棒”的事情。标准协作式取消模式,为了这取消这个操作,首先必须创建一个System.Threading.CancellationTokenSource 对象。这个对象包含了和怪取消相关的所有状态。构造好一个CancellationTokenSource 之后,可

2020-11-28 17:05:29 153

原创 .net 易失字段

internal sealed class ThreadSharingData{ private Int32 m_flag =0; private Int32 m_value =0; //由一个线程执行 public void Thread1() { // 注意:以下两行代码可以按相反的顺序执行 m_value =5; m_flag =1; } // 这个方法由另一个线程执行 public void Thread2() { // 注意:m_value 可能在m_fla

2020-11-26 21:54:54 68

原创 .net 线程执行上下文

每个线程都关联了一个执行上下文数据结构。执行上下文(execution context)包含的东西有安全设置(压缩栈,Thread的Principal 属性和windows身份)、宿主设置以及逻辑调用上下文数据的LogicSetData和LogicalGetData 方法。线程执行代码时,有的操作会受到线程的执行上下文设置的影响。理想情况下,每当一个线程使用另一个线程执行任务时,前者的执行上下文应该流向辅助线程。这就确保了辅助线程执行的任何操作使用的是相同的安全设置和宿主设置。还确保了初始线程的逻辑调用上下

2020-11-23 22:59:32 260

原创 .net CLR线程池

创建和销毁线程是一个昂贵的操作,要耗费大量的时间。另外太多会浪费内存资源。由于操作系统必须调度可运行的线程并执行上下文切换,所以太多的线程还有损于性能。为了改善这个情况,CLR包含了代码来管理他自己的线程池。可将线程池想象成一个线程集合。每CLR一个线程池;这个线程池由CLR控制的所有AppDomain共享。如果一个进程中加载了多个CLR, 那么每个CLR都有它自己的线程池。CLR初始化时,线程池中是没有线程的。在内部,线程池维护了一个操作请求的队列。应用程序想执行一个异步操作,就调用某个方法,将一个记录

2020-11-22 19:22:40 197 1

原创 .net 线程开销

对于每个线程中,都有以下要素:1,线程内核对象(thread kernel object) OS为系统中创建的每个线程都分配并初始化这种数据结构之一。在该数据结构中,包含一组对线程进行描述的属性。数据结构中还包含所谓的线程上下文(thread context)。上下文是一个内存块,其中包含了CPU的寄存器集合。windows在一台使用x86 CPU的计算机上运行是,线程上下文使用约700字节的内存。对于x64和IA64 CPU,上下文分别使用约1240字节和2500字节的内存。2,线程环境块(threa

2020-11-21 20:03:43 97

原创 .net 委托和接口的逆变和协变泛型类型实参

委托的每个泛型参数都可标记为协变量或者逆变量。利用这个功能,可将泛型委托类型的一个变量转型为同一个委托类型的另一个变量,后者的泛型参数类型不同。泛型类型参数可以是以下任何一种形式。1,不变量(invariant) 意味着泛型类型参数不能更改。2,逆变量(contravariant)意味着泛型类型参数可以从一个基类型更改为该类的派生类。在C#中,用in关键字标记逆变量形式的泛型类型参数。逆变量泛型类型参数只出现在输入位置,比如作为方法的参数。3,协变量(covariant)意味着泛型类型参数可以从一个派

2020-11-20 22:06:49 133

原创 .net 委托的揭秘

从表面看,委托似乎很容易使用:用C#的delegate关键字定义,用熟悉的new操作符构造委托实例,用熟悉的方法调用语法来调用回调函数(只是要用引用了委托对象的一个变量来替代方法名)。然而,实际情况比前面几个例子演示的要复杂一些。编译器和CLR在幕后做了大量工作来隐藏复杂性。首先让我们重新审视下面一行代码:internal delegate void Feeback(Int32 value)看到这行代码后,编译器实际会像下面这样定义一个完整的类:internal class Feeback : S

2020-11-17 22:28:18 126

原创 .net 谨慎使用显示接口方法实现

1,没有文档解释一个类型具体如何实现EIMI, 也没有Microsoft Visual studio 智能感知支持。2,值类型的实例在转型为接口时装箱。3,EIMI 不能由派生类型调用。在.net framework 参考文档中查看一个类型的方法时,会列出显示接口方法实现EIMI, 但没有提供类型特有的帮助,只能看到接口方法的常规性帮助。例如int32类型的文档只是说他实现了IConvertible接口的所有方法。能做到这一步当然不错,因为开发人员指导这些方法时存在的。但是,这也让开发人员感到困惑,因

2020-11-16 23:04:26 104

原创 .net 继承接口

C# 编译器要求将用于实现一个接口的方法标记为public . CLR要求将接口方法标记为virtual. 如果在源代码中没有显示地将方法标记为virtual, 编译器会将它们标记为virtual和sealed; 这会阻止派生类重写接口方法。如果显式地将方法标记为virtual, 编译器就会将该方法标记为virtual(并保持它的密封状态)。这样一来。派生类就能重写它。如果一个接口方法是sealed的,派生类就不能重写它。不过派生类可以重新继承同一个接口,并可为该接口的方法提供它自己的实现。在一个对象上调

2020-11-15 22:56:29 476

原创 .net 泛型的优势

泛型为开发人员提供了以下优势:1,源代码保护,使用一个泛型算法的开发人员不需要访问算法的源代码。然而,使用C++模板的泛型技术时,算法的源代码必须提供给准备使用算法的用户。2,类型安全,将一个泛型算法应用一个具体的类型时,编译器和CLR能理解开发人员的意图,并保证只有与指定数据类型兼容的对象才能随同算法使用。若试图使用不兼容类型的一个对象,会造成编译时错误,或在运行时抛出异常。在上例中,试图将一个String对象传给Add方法,造成了编译器报错。3,更加清晰的代码,由于编译器强制类型安全性,所以减少了

2020-11-10 22:20:42 270

原创 .net 设计要公开事件的类型

开发人员要经历多个步骤,才能定义好一个公开了一个或多个事件成员的类型。本节详细描述每一个不要的步骤。MailManager 示例应用程序展示了MailManager类型、Fax类型和Pager类型的所有源代码。注意,Pager类型和Fax类型几乎完全相同。1,第一步:定义类型来容纳所有需要发送给事件通知接收者的附加信息事件引发时,引发事件的对象可能希望向接收事件通知的对象传递一些附加的信息。这些附加的信息需要封装到它自己的类中,该类通常包含一组私有字段,以及一些用于公共这些字段的只读公共属性。根据约定,

2020-11-09 22:55:40 110

原创 .net 分部类,结构和接口

本节要讨论分部类、结构和接口。要注意的是,这个功能完全是由C#编译器提供的还有其他一些编译器也提供了这个功能,CLR对于分部类,结构和接口是yiwusuozhi 的。partial这个关键字告诉C#编译器,一个类,结构或者接口的定义源代码可能要分散到一个或者多个源代码文件中。主要有三方面的原因促使我们将某个类型的源代码分散到多个文件中。1,源代码控制 假定一个类型的定义由许多源代码构成,一个程序员把它从源代码控制系统中签出以进行修改。没有其他程序员能同时修改这个类型,除非以后执行一次合并。使用parti

2020-11-08 20:48:08 160

原创 .net 对象的相等性和同一性

开发人员经常都要边写代码来比较不同的对象。例如,有时需要将对象放到一个集合中,并编写代码对集合中的对象进行排序、搜索或者比较。本节将讨论相等性和同一性,还将讨论如何定义一个正确实现了对象相等性的类型。System.Object类型提供了一个名为Equals的虚方法,它的作用是在两个对象包含相同的值的前提下返回true . object 的Equals方法是像下面这样实现的:public class Object{ public virtual Boolean Equals(Object obj){

2020-11-07 20:13:37 154

原创 .net 值类型的装箱和拆箱

值类型是比引用类型更“轻型”的一种类型,因为它们不作为对象在托管堆中分配,不会被垃圾回收,也不通过指针来引用。但在许多情况下,都需要获取对值类型的一个实力的引用。例如假定要创建一个ArrayList对象(System.Collections命名空间中定义的一个类型)来容纳一组Point结构,那么代码可能像下面这样:struct Point{ public Int32 x,y;}public sealed class Program{ public static void Main(){ Ar

2020-11-07 12:10:59 166

原创 .net 引用类型和值类型

CLR支持两种类型:引用类型和值类型。虽然FCL中大多数类型都是引用类型,但程序员用的最多的还是值类型。引用类型总是从托管堆上分配的,C#的new操作符会返回对象的内存地址——也就是指向对象数据的内存地址。使用引用类型时,必须注意到一些性能问题。首先考虑以下事实。1,内存必须从托管堆上分配。2,堆上分配的每个对象都有一些额外的成员,这些成员必须初始化。3,对象中的其他字节(为字段而设)总是设为零。4,从托管堆上分配一个对象时,可能强制执行一次垃圾收集操作。如果所有类型都是引用类型,应用程序的性能将

2020-11-06 23:04:05 103

翻译 .net 类型转换

CLR 最重要的特性之一就是类型安全性。在运行时,CLR总是知道一个对象是什么类型。调用GetType方法,总是知道一个对象确切的类型是什么。由于这个方法是非虚方法,所以一个类型不可能伪装成另一个类型。开发人员经常需要将一个对象从一种类型转换为其他各种类型。CLR允许将一个对象转换为它的(实际)类型或者它的任何基类型。每种编程语言都规定了开发人员具体如何进行这种转型操作。例如,C#不要求任何特殊语法即可将一个对象转换为它的任何基类型,因为向基类型的转换被认为是一种安全的隐式转换。然而,将对象转换为它的派生

2020-11-05 21:55:51 376

翻译 .net 使用CriticalFinalizerObject 类型确保终结

为了简化编程,System.Runtime.ConstrainedExecution 命名空间定义了一个CriticalFinalizerObject类,其形式如下:public abstract class CriticalFinalizerObject{ protected CriticalFinalizerObject(){ /* 这里没有代码*/} // 这是一个Finalize方法 ~CriticalFinalizerObject(){/* 这里没有代码*/ }}我知道,这个类看

2020-11-05 19:36:12 123

翻译 .net 使用终结操作来释放本地资源

大多数类型只需内存就可以正常工作。但是,也有一些类型除了要使用内存,还要使用本地资源。例如,System.IO.FileStream 类型需要打开一个文件(本地资源)并保存文件的句柄。然后该类型的Read和Write方法用该句柄来操作文件。类似地,System.Threading.Mutex类型要打开一个Windows互斥体内核对象(本地资源)并保存其句柄,并在调用Mutex的方法时使用该句柄。终止(finalization)是CLR提供的一种机制,允许对象在垃圾回收期回收其内存之前执行一些得体的清理工

2020-11-03 22:28:02 316

原创 .net 垃圾回收与调试

using System;using System.Threading;public static class Program{ public static void Main(){ //创建一个Timer对象,每隔2000毫秒就调用一次TimerCallBack方法 Timer t= new Timer(TimerCallBack, null, 0, 2000); Console.ReadLine(); } private static void TimerCallBac

2020-11-02 23:07:55 98

原创 .net 基元用户模式和内核模式构造

基元线程同步构造。所谓基元,我的意思是指可以在代码中使用的最简单的构造。由两种基元构造:用户模式(user-mode)和内核模式(kenel-mode).应该尽量使用基元用户模式构造,它们的速度要显著快于内核模式的构造。这是因为它们使用了特殊CPU指令来协调线程。这意味着协调是在硬件中发生的(所以才这么快)。但是,这同时意味着Microsoft Windows操作系统永远检测不到一个线程在一个基元用户模式中构造上的阻塞了。由于在用户模式的基元构造上阻塞的一个线程池线程永远不认为已经阻塞,所以线程池不会创建一

2020-10-31 20:38:54 240

原创 .net 类库和线程安全

现在,我们简单地谈一谈类库和线程同步。Microsoft的Framework Class Library(FCL) 保证所有静态方法都是线程安全的。这意味着假如两个线程同时调用一个静态方法,不会由数据被损坏。FLC必须在内部做到这一点,因为开发不同程序集的多个公司不可能事先协商好使用一个锁来仲裁对资源的访问。Console类包含一个静态字段,类的许多方法都要获取和释放这个字段上的锁,以确保一次只有一个线程访问控制台。要郑重声明的是,使一个方法线程安全,并不是说它一定要在内部获取一个线程同步锁。一个线程安全

2020-10-31 19:36:50 448

原创 .net线程核心处理机制(1)

一个线程池阻塞(block)时,线程池会创建额外的线程,而创建、销毁和调度线程所需的时间和内存资源时相当昂贵的。另外,许多开发人员在看见自己程序中的线程没有在任何有用的事情时,他们的习惯时创建更多的线程,期望新线程能做有用的事情。为了构建可伸缩的、具有良好响应能力的应用程序,关键在于不要阻塞你拥有的线程,使它们能用于执行其他任务。多个线程同时访问共享资源时,线程同步用于防止数据损坏。我之所以强调“同时”,是因为线程同步问题就是计时问题。如果有一些数据需要由两个线程访问,但那些线程不可能同时接触到数据,就完

2020-10-31 18:50:06 73

原创 .net 垃圾回收算法

垃圾回收器检查托管堆中是否有应用程序不再使用的任何对象。如果有,它们使用的内存就可以回收(如果一次垃圾回收之后,堆中仍然没有可用的内存,new操作符将会抛出一个OutOfMemoryException)。垃圾回收期如何知道应用程序正在使用一个对象?你或许已经想到,这不是一个三言两语就能说清楚的问题。每个应用程序都包含一组根(root)。每个根都是一个存储位置,其中包含指向引用类型对象的一个指针。该指针要么引用托管堆中的一个对象,要么为NULL 。例如,类型中定义个任何静态字段都认为是一个根。除此以外,任何

2020-10-31 12:27:00 81

原创 .net 从托管堆分配资源

CLR要求所有的资源都从托管堆(managed heap)分配。这个堆和c运行时堆非常相似,只是你永远不从托管堆中删除对象——应用程序不需要的对象会自动删除。这自然引起一个问题:“托管堆如何知道应用程序不再用一个对象?”我稍后就会回答这个问题。目前使用的垃圾回收算法有好几种。每种算法都针对特定环境进行优化,能提供这种环境下最佳的性能。本章关注的是Microsoft .NET Framework 的CLR所采用的垃圾回收算法。先从最基本的概念讲起。进程初始化,CLR要保留一块连续的地址空间,这个地址空间最

2020-10-31 10:34:28 59

原创 .net自动内存管理(垃圾回收)

一,理解垃圾回收平台的基本工作原理每个程序都要使用这样或那样的资源,比如文件、内存缓冲区、屏幕空间、网络连接、数据库资源等。事实上,在面向对象的环境中,每个类型都代表可供程序使用的一种资源。要使用这些资源,必须为代表资源的类型分配内存。以下是访问一个资源所需的具体步骤1,调用IL指令newobj, 为代表资源的类型分配内存。在C#中使用new操作符,编译器就会自动生成该指令。2,初始化内存,设置资源的初始状态,使资源可用。类型的实例构造器负责设置该初始状态。3,访问类型的成员来使用资源。4,摧毁资

2020-10-29 22:45:42 313

原创 .net异常处理的性能问题

开发人员社区经常就异常处理的性能问题展开活跃争论。有人说异常处理性能很差,以至于他们根本就不打算使用。但是,我认为在面向对象平台中,异常处理不是一个可有可无的东西,而是必须的!另外,假若不用它,有什么是可以替代的呢?让方法返回bool值类型标识成功或失败,还是使用某种错误代码enum类型?如果真的这样做,那么两个世界中最坏的情况都会发生;CLR和类库都会抛出异常而你的代码会返回错误代码。现在你的代码两者都要应对。异常处理和较常规的报告异常的方式相比,很难看出两者的性能差异。如果写代码检查每个方法调用的返回

2020-10-28 21:30:36 220

原创 net 异常和状态管理(3)

一,发生异常以后为了确保清理代码的执行是如此重要,以至于许多编程语言都提供了一些构造来简化清理代码的编写。例如只要使用了lock, using 和foreach 语句,C#编译器就会自动生成try/finally块。另外,重写一个类的析构器(Finalize方法)时,C#编译器也会生成try/finally块。使用这些构造时,编译器将你写的代码放到try块内部,并自动将清理代码放到finally块中。具体如下所示。1)使用lock语句时,锁会在finally块中释放。2)使用using语句时,会在fin

2020-10-27 21:13:54 154

原创 .net 异常和状态管理(2)

       关于异常的发生有意见好事在于,未处理异常会造成应用程序终止。之所以说这是一件好事,是因为可以在测试期间快速发现问题。利用由未处理的异常提供的信息(错误信息和堆栈跟踪),通常足以完成对代码的修正。当然,许多开发人员不希望他们的应用程序在测试和部署之后继续发生意外终止的情况,所以他们会插入代码来捕捉System.Exception,也就是所有异常类型的基类。然而,如果捕捉System.Exception并允许应用程序继续运行,一

2020-10-26 22:50:39 125

原创 .net 异常和状态管理(1)

.net核心机制1,定义异常设计类型时,首先要想好类型的各种使用情况。类型名称通常是一个名词,例如FileStream或者StringBuilder。然后,要为类型定义属性、方法、事件等。这些成员(属性的数据类型、方法的参数、返回值等)的定义方式就是类型的编程接口。这些成员代表类或者类型实例可以执行的行动。行动成员通常用动词表示,例如Read,Write,Flush,Append,Insert 和Remove等。当行动成员不能完成任务时,就应抛出异常。定义:异常是指成员没有完成它的名称宣称可以完成的行

2020-10-25 11:52:07 79

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除