随笔分类 - .NET基础
摘要:在"线程系列04,传递数据给线程,线程命名,线程异常处理,线程池"中,我们已经知道,每个进程都有一个线程池。可以通过TPL,ThreadPool.QueueUserWorkItem,委托与线程池交互。本篇体验:通过查看CLR代码来观察线程池及其线程。 □ 通过编码查看线程池和线程 使用ThreadPool的静态方法QueueUserWorkItem把线程放入线程池,来看线程池线程和主程序线程的...
阅读全文
摘要:SOS (Son of Strike)调试扩展可以让我们在调试过程中查看CLR运行代码。SOS.dll随.NET一起安装,对于.NET 4.0来说,SOS.dll的所在位置是:C:\Windows\Microsoft.NET\Framework\v4.0.30319\SOS.dll。 □ 安装Debugging Tools for Windows 在使用SOS之前,需要安装调试工具,在这里...
阅读全文
摘要:有时候,我们希望手动结束一个线程。比如说,当客户端满足某种条件,让线程就此结束。如何设计呢? 线程间肯定要共享数据,假设把共享数据默认值设置成true,客户端线程在满足某种条件时把共享数据设置成false。而另外一个线程,如果共享数据一直是true,它就一直执行程序,直到共享数据为false,该线程就结束。 class Program { private stat...
阅读全文
摘要:本篇体验:如何传递数据给线程,如何给线程命名,线程的异常处理,线程池。实在是太基础的部分。 □ 传递数据给线程 ※ 使用Lambda表达式 class Program { static void Main(string[] args) { Thread t = new Thread(() => Say("hello", "w...
阅读全文
摘要:多线程编程,有时希望每个线程的数据相互隔离互不影响,有时却希望线程间能共享数据,并保持同步。本篇体验多线程共享和不共享数据。 □ 多线程不共享数据 对于多线程,CLR到底是怎样为它们分配内存栈空间呢?是"一个萝卜一个坑",每个线程都有自己的栈空间;还是"大树底下好乘凉",所有的线程共享同一个栈空间? 我们让2个线程执行相同的静态方法,用到相同的变量,通过打印变量来求证多线程栈空间的分配情况。 ...
阅读全文
摘要:当面对一个耗时较长的任务时,我们可以把这个任务切分成多个部分,然后同时交给多个线程处理。 □ 统计字节数组一个比较耗时的方式 以下来统计一个字节数组的大小。 class Program { static byte[] values = new byte[500000000]; static void Main(string[] args) ...
阅读全文
摘要:在控制台应用程序集中,Main方法开始的是一个线程。如果要再创建线程,需要用到System.Threading这个命名空间。 □ 线程是怎样工作的? CLR维护着一个叫"thread scheduler"的机制,这个机制与操作系统交互。"thread scheduler"保证所有的线程有合适的执行时间,那些等待或被阻塞的线程不会占有CPU时间。在单处理器计算机上,"thread schedul...
阅读全文
摘要:在"C#中,什么时候用yield return"中,我们了解到:使用yield return返回集合,不是一次性加载到内存中,而是客户端每调用一次就返回一个集合元素,是一种"按需供给"。本篇来重温yield return的用法,探秘yield背后的故事并自定义一个能达到yield return相同效果的类,最后体验yield break的用法。 □ 回顾yield return的用法 以下代码...
阅读全文
摘要:在"C#中List是怎么存放元素的"中,分析了List的源码,了解了List是如何存放元素的。这次,就自定义一个泛型集合类型,可实现添加元素,并支持遍历。 该泛型集合类型一定需要一个添加元素的方法,在添加元素的时候需要考虑:当添加的元素超过当前数组的容量,就让数组扩容;为了支持循环遍历,该泛型集合类型必须提供一个迭代器(实现IEnumerator接口)。 public class MyL...
阅读全文
摘要:假设有一个规定长度的数组,如何扩容呢?最容易想到的是通过如下方式扩容: class Program { static void Main(string[] args) { int[] arrs = new[] {1, 2, 3, 4, 5}; arrs[5] = 6; } }
报错...
阅读全文
摘要:查看是否安装.NET Framework→%SystemRoot%\System32→如果有mscoree.dll文件,表明.NET Framework已安装 查看安装了哪些版本的.NET Framwork→开始-运行→输入cmd→输入如下命令dir %WINDIR%\Microsoft.Net\Framework\v* 查看安装的所有CLR版本→打开"VS2012命令提示"→输入CLRV...
阅读全文
摘要:本篇体验静态变量、静态构造函数和静态类。 静态变量 静态变量位于栈上,它是一个全局变量,在编译期就已经生成。 public class Cow { public static int count; private int id; public Cow() { id = ++count; ...
阅读全文
摘要:在C#中,sizeof用来计算类型的大小,单位是字节。有这样的一个类: public class MyUglyClass { public char myChar1; public int myInt; public char myChar2; } 在客户端,试图使用sizeof计算该类型的大小。 class Prog...
阅读全文
摘要:每个托管堆上的对象实例除了包含本身的值外,还包括:○ Type Object Ponter: 指向Type对象实例。如果是同类型的对象实例,就指向同一个Type对象实例。○ Sync Block Index:在多线程情况下用来控制同步 namespace ConsoleApplication1
{ class Program { static void Main(...
阅读全文
摘要:本篇体验引用类型转换:子类转换成父类,父类转换成子类,以及不是子父级关系类之间的转换。 □ 隐式转换:子类转换成父类 public class Animal { public int _age; public Animal(int age) { this._age = age; } }...
阅读全文
摘要:假设有这样一个值类型struct。 public struct Size { public int Length; public int Width; public int Area() { return Length*Width; } } □ 客户端,给所有stru...
阅读全文
摘要:当把一个值类型赋值给引用类型,这个过程可以看作是"装箱"。 object a = 10;
以上,堆栈上的过程大致是:1、在栈上开辟空间给变量a2、在堆上开辟空间,习惯上把该空间看作是"箱子"3、把10"装箱" 变量a指向堆上值为10的对象,换句话说,变量a的值是堆上对象的地址。 现在,如果我们想让a=11,可能首先想到的是:让"箱子"内的10自增1,变成11。 尝试这样做: ojec...
阅读全文
摘要:本篇主要体验,在存在多个版本程序集的情况下,如何让CLR选择哪个版本程序集运行,以及程序集版本的切换。 分别生成非强名称程序集不同版本 □ 生成某个版本的程序集 →清理F盘as文件夹,剩下如下文件 →查看Cow.cs文件 using System;
using System.Reflection;
[assembly: AssemblyVersion("3.3.3.3")]
publi...
阅读全文
摘要:本篇体验C#编译器和CLR运行时如何查找程序集,并自定义CLR运行时查找程序集的方式。 □ C#编译器和CLR运行时如何查找程序集 C#编译器在哪里?--在C:\Windows\Microsoft.NET\Framework\v4.0.30319中 →删除F盘as文件夹中所有的exe和dll文件→把上一篇全局程序集缓存文件夹(C:\Windows\Microsoft.NET\assembly\...
阅读全文
摘要:全局程序集缓存(GAC:Global Assembly Cache)用来存放可能被多次使用的强名称程序集。当主程序需要加载程序集的时候,优先选择到全局程序集缓存中去找寻需要的程序集。 为什么需要全局程序集缓存?假设程序A引用B程序集,程序C也引用B程序集,在这种情况下,可以把B程序集放到一个全局程序集缓存中是明智的做法。 □ 使用全局缓存程序集 →删除F盘as文件夹中所有dll和exe后缀...
阅读全文
浙公网安备 33010602011771号