介绍:以前没有学习过C#这个语言,我是刚刚从大学毕业的学生,个人专业是嵌入式系统工程(底层驱动ARM、Linux、单片机),本人很喜欢计算机,更喜欢软件开发(应用层)的这种工做,只是当时考大学时没有过多的了解选错了专业,毕业后开始找工做一直在找我喜欢的应用层行业,找了30多家公司终于有一个愿意培养个人了(主要是我不会应用层的技术,没有公司要我,因此找的公司不少,但我没放弃),在公司的三个月里我一边工做一边学习,如今把我所学到的都记录下来,下面有的代码我是复制其余人的,也别介意我是研究了很久了学会了,方便记录我就黏贴在我这里。你们能够学习,参考,指点错误,我也当个笔记方便之后复习。javascript
有个提示:我是有过C语言底子的,学习C#时那些简单基础的语法很快就能懂得使用,我相信学过相似的语言(Java、C++)都能一看就会那些简单基础,假如不会那请先学习编程的简单语法知识(我博客里也有简单语法知识),因此那些基础性东西我就不写了。我用的软件是vs2010,sqlserver2008。基础部分大多数是”控制台应用程序“,后面一点点延伸winform应用程序,web程序内的(HTML、css、javascript、jpuery、div+css)、MVC,ASP.NET。重点练习项目:超市管理系统、音乐播放器、局域网聊天(tcp/udp)、外网聊天(我相信不少程序员不会写)css
想成功,多动脑!不要作个“手重眼轻”,能看会 未必能会写,不少都是用代码来说解,全是“干货”。html
接下来就是我这三个月的历程:java
目录node
1、基础c++
1.多态、继承程序员
1)、virtual虚方法多态web
2)、abstract抽象方法面试
2.泛型sql
1)、泛型方法
2)、泛型类
3)、泛型接口
4)、泛型约束
3.集合
1)、泛型集合(list)
2)、ArrayList集合
3)、Dictionary键值对集合
4)、Hashtable键值对集合
感受少了什么,仔细想一想我少写一个“枚举”,我就把枚举插在这个位置吧,临时在网上找的(不要夸我太懒,用到枚举的地方真的少,我就懒得写了)
5)、枚举
4.拆装箱
5.逆变和协变
6.工厂模式
7.部分类partial
8.密封类sealed
9.重写ToString方法
10.属性
11.里氏转换is、as
12.接口
13.接口与抽象类的区别
14.流操做
15.序列化、反序列化(XML和二进制)
16.PropertyInfo 反射
17.GUID编号
18.StringBuilder
19.委托、事件
20.编写DLL文件、调用DLL文件、传参、返回值
21.字符串大小写转换
22.字符串大小写转换
23.单例模式
24.文件、文件夹操做(path、File、Directory)
项目:----对基础知识的巩固复习
25.超市管理系统(控制台应用程序)
26.小游戏(石头剪刀布)
27.英汉词典
28.音乐播放器(winform)--------------这个软件会作了,才能表明C# winform开发 “基础”已经学会了
--------------------基础基本差很少了,等到所有结束后,咱们再来更详细练习基础部分----------------------
2、线程
1.建立线程_前台_后台_挂起_唤醒_阻塞_终止_优先级
2.同步
3.线程池
4.异步
3、进程
1.进程简单操做
2.进程间通讯
项目练习:映射综合
4、网络编程
大概了解tcp、udp、socket工做原理,代码是如何编写的,先不须要马上学会,下面我还会很详细你讲解的
了解部分:
1.tcp
2.udp
3.标准的socket
详细讲解:---->>>>(我花了两块五买的教程,拿出来了给你们分享,代码已经全是我亲手写的了)
1.复习委托机制
2.复习回调机制
3.TCP服务端
4.同步TCP客户端
5.异步TCP客户端
6.UDP进程通讯
7.UDP广播和组播
8.局域网聊天室
9.WebClient
10.打洞(能够不用学 ,高端技术很难得)
项目练习:
局域网聊天(简单)、
局域网聊天(仿QQ)、
广域网聊天(仿QQ,很难,学不会就不要学了,嘿嘿不少程序员都不会的)
串口通信(详细讲解,我认为串口要好好学习,如今的能够都是软件和硬件搭配的好才最值钱,就不过多解释了)
---------------------------------------------------------------------------------------------------------------
数据库了
第一部分:
ac
my
sq
他们的工做原理和操做
第二部分:
和winform的搭配使用
三层架构
项目:管理系统之类的
第三部分(自选喽)
ao很火
-----------------------------------------------------------------------------------------------------------------------------
WPF
把winform管理系统之类的项目改写成WPF
----------------------
ASP.NET
html css js jq MVC
把winform管理系统之类的项目改写成ASP.NET
--------------------------------------------
细致化的复习winform控件之类的知识
-----------------------------------------
在来几个其余技术
---------------------------------------
结束!发言
1、基础
1.多态、继承

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 //实现多态的手段 7 //1)、虚方法 8 //步骤: 9 //一、将父类的方法标记为虚方法 ,使用关键字 virtual,这个函数能够被子类从新写一个遍。 10 //理解:经过继承实现的不一样对象调用相同的方法,表现出不一样的行为,称之为多态。 11 12 //2)、抽象类 13 //当父类中的方法不知道如何去实现的时候,能够考虑将父类写成抽象类,将方法写成抽象方法。 14 //派生类要实现抽象方法,派生抽象类能够不用重写父类抽象方法 15 //抽象类和接口 很像,我会在写接口时介绍他俩的区别 16 17 //3)、继承 18 //新类(即派生类)将获取基类的全部非私有数据和行为以及新类为本身定义的全部其余数据或行为。 19 //子类实现父类的属性和方法,并在此基础上进行相关的扩展 20 21 //下面是虚方法的多态: 22 namespace _1.多态_虚方法_ 23 { 24 public class Animal 25 { 26 public virtual void Eat()//虚方法 virtual 27 { 28 Console.WriteLine("动物会吃东西"); 29 } 30 } 31 32 public class Dog : Animal//继承Animal Animal为父类 33 { 34 public override void Eat()//重写虚方法 override 35 { 36 Console.WriteLine("狗也会吃东西"); 37 } 38 } 39 40 public class Cat : Animal 41 { 42 public override void Eat() 43 { 44 Console.WriteLine("猫也会吃东西"); 45 } 46 } 47 48 class Program 49 { 50 static void Main(string[] args) 51 { 52 //各类实现 体会吧 53 /*********************/ 54 Animal animal = new Animal(); 55 animal.Eat(); 56 Dog dog = new Dog(); 57 dog.Eat(); 58 Cat cat = new Cat(); 59 cat.Eat(); 60 /*******************/ 61 Console.WriteLine(); 62 /********************/ 63 Animal[] al = new Animal[3]; 64 al[0] = new Animal(); 65 al[0].Eat(); 66 al[1] = new Dog(); 67 al[1].Eat(); 68 al[2] = new Cat(); 69 al[2].Eat(); 70 /*********************/ 71 Console.WriteLine(); 72 /**********************/ 73 Animal a1 = new Animal(); 74 a1.Eat(); 75 Animal a2 = new Dog(); 76 a2.Eat(); 77 Animal a3 = new Cat(); 78 a3.Eat(); 79 80 Console.ReadKey(); 81 } 82 } 83 }

1 using System;
2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 //下面是抽象类的多态: 7 namespace _2.多态_抽象_ 8 { 9 public abstract class Animal 10 { 11 public abstract void Eat();//请注意抽象方法没有方法体 12 } 13 14 public abstract class Person:Animal 15 { 16 public abstract void 喝拉撒睡(); 17 } 18 19 public class Me : Person 20 { 21 public override void Eat() 22 { 23 Console.WriteLine("我会吃"); 24 } 25 //两个抽象方法缺一不可,要所有实现 26 public override void 喝拉撒睡() 27 { 28 Console.WriteLine("我还会喝拉撒睡"); 29 } 30 } 31 32 public class You : Animal //You继承Animal 继承用: 33 { 34 public override void Eat() 35 { 36 Console.WriteLine("你就是个吃货"); 37 } 38 } 39 40 class Program 41 { 42 static void Main(string[] args) 43 { 44 //Animal animal = new Animal();//抽象类不能被继承!!!! 45 Me m = new Me(); 46 m.Eat(); 47 m.喝拉撒睡(); 48 You y = new You(); 49 y.Eat(); 50 //////////// 51 Console.WriteLine(); 52 //////////// 53 Person[] p = new Person[1]; 54 Animal[] a=new Animal[2]; 55 a[0] = new Me(); 56 p[0]= new Me(); 57 p[0].Eat(); 58 p[0].喝拉撒睡(); 59 60 a[1] = new You(); 61 a[1].Eat(); 62 63 Console.ReadKey(); 64 } 65 } 66 }
2.泛型

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 泛型方法 7 { 8 class Program 9 { 10 static void fx<T>(ref T l, ref T r) 11 { 12 //l和r值交换 13 T temp; 14 temp = l; 15 l = r; 16 r = temp; 17 } 18 19 static void Main(string[] args) 20 { 21 int a = 1; 22 int b = 2; 23 24 //fx<int>(ref a, ref b); 25 fx(ref a, ref b);//这两种方式是同样的 26 27 Console.WriteLine(a+" "+b); 28 Console.ReadKey(); 29 } 30 } 31 }

1 using System;
2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 泛型类 7 { 8 //我在这把一般你们爱写的T写成A,是为了让你们知道这知道表明一个类型不是固定的T 9 class FxClass<A> 10 { 11 public void Fx<A>(ref A l, ref A r) 12 { 13 A temp; 14 temp = l; 15 l = r; 16 r = temp; 17 } 18 } 19 20 class Program 21 { 22 static void Main(string[] args) 23 { 24 int a = 1; 25 int b = 2; 26 27 FxClass<int> fxl = new FxClass<int>(); 28 fxl.Fx<int>(ref a, ref b); 29 Console.WriteLine(a + " " + b); 30 Console.ReadKey(); 31 } 32 } 33 }

1 using System;
2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 泛型接口 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 Student stu = new Student(); 13 Console.WriteLine(stu.Jia(2, 3)); 14 Console.WriteLine(stu.Jian(3, 1)); 15 Console.Read(); 16 } 17 } 18 19 //定义泛型接口 20 interface Icomuter<T> 21 { 22 //定义泛型方法 23 T Jia(T item1, T item2); 24 T Jian(T item1, T item2); 25 26 } 27 28 //继承泛型接口 29 class Student : Icomuter<int> 30 { 31 //继承实现泛型方法 32 public int Jia(int item1, int item2) 33 { 34 return item1 + item2; 35 } 36 public int Jian(int item1, int item2) 37 { 38 return item1 - item2; 39 } 40 } 41 }

1 using System;
2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 #region .net泛型约束: 7 //所谓泛型,即经过参数化类型来实如今同一份代码上操做多种数据类型。 8 //泛型编程是一种编程范式,它利用“参数化类型”将类型抽象化,从而实现更为灵活的复用。 9 10 //在定义泛型类时,能够对客户端代码可以在实例化类时用于类型参数的类型种类施加限制。 11 //若是客户端代码尝试使用某个约束所不容许的类型来实例化类,则会产生编译时错误。 12 //这些限制称为约束。约束是使用 where 上下文关键字指定的。 13 #endregion 14 15 #region 约束 说明 16 //T:struct 17 //类型参数必须是值类型。能够指定除 Nullable 之外的任何值类型。 18 //T:class 19 //类型参数必须是引用类型,包括任何类、接口、委托或数组类型。 20 //T:new() 21 //类型参数必须具备无参数的公共构造函数。当与其余约束一块儿使用时,new() 约束必须最后指定。 22 //T:<基类名> 23 //类型参数必须是指定的基类或派生自指定的基类。 24 //T:<接口名称> 25 //类型参数必须是指定的接口或实现指定的接口。能够指定多个接口约束。约束接口也能够是泛型的。 26 //T:U 27 //为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。这称为裸类型约束. 28 #endregion 29 30 namespace 泛型约束 31 { 32 class Program 33 { 34 static void fx<T>(ref T l, ref T r) where T : IComparable //where是约束T类型在IComparable范围内 35 { 36 T temp; 37 temp = l; 38 l = r; 39 r = temp; 40 } 41 42 static void Main(string[] args) 43 { 44 int a = 1; 45 int b = 2; 46 47 //fx<int>(ref a, ref b); 48 fx(ref a, ref b);//这两种方式是同样的 49 Console.WriteLine(a + " " + b); 50 Console.ReadKey(); 51 } 52 } 53 }
3.集合

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 //泛型集合 很简单 我就介绍一下几个部分 7 namespace _1.泛型集合_list_ 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 List<int> list = new List<int>(); 14 list.Add(1); 15 list.Add(2); 16 list.Add(3); 17 18 list.AddRange(new int[]{4,5,6});//添加集合 19 20 list.AddRange(list);//添加本身 21 22 int[] ii = list.ToArray();//转为数组 23 24 //怕误会觉得泛型集合只能够操做整数 25 List<string> lt = new List<string>(); 26 //其实都是同样的,我就很少写了 27 lt.Add("请叫我:毕小帅");//你们都叫我“小帅”嘿嘿 28 lt.Add("我叫:小毕"); 29 30 //输出 31 for (int i = 0; i < list.Count; i++) 32 { 33 Console.Write(list[i].ToString()); 34 } 35 Console.WriteLine(); 36 for (int i = 0; i < lt.Count; i++) 37 { 38 Console.WriteLine(lt[i].ToString()); 39 } 40 Console.WriteLine(); 41 //也能够用foreach 42 //foreach在数据多的时候能比for的速度快 43 foreach (var item in list) 44 { 45 Console.Write(item.ToString()); 46 } 47 48 Console.ReadKey(); 49 } 50 } 51 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Collections; 6 7 namespace ArrayList集合 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 ArrayList al = new ArrayList(); 14 //我喜欢它的最重要的一点就是:他什么类型均可以储存 15 //还不用像数组同样定义长度 16 //和list集合不一样的就是不用定义类型 17 //缺点 读取时须要拆装箱 18 al.Add(1); //添加数字 19 al.Add("abc"); //添加字符串 20 al.Add('d'); //添加字符 21 22 al.AddRange(new char[] { 'e', 'f' });//添加数组 23 al.AddRange(al); //添加集合 本身 24 25 for (int i = 0; i < al.Count; i++) 26 { 27 Console.WriteLine(al[i].ToString()); 28 } 29 30 Console.Read(); 31 } 32 } 33 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace Dictionary键值对集合 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 //他和list集合性质差很少,先肯定了类型 13 Dictionary<String, String> dy = new Dictionary<String, String>(); 14 15 dy.Add("key1", "value1");//添加 16 17 dy["key2"] = "value2";//若是键不存在也能够经过此方法来添加键/值对 18 19 dy.ContainsKey("key1"); //判断该键是否存在 20 21 foreach (Object key in dy.Keys) //遍历key 22 { } 23 foreach (Object value in dy.Values)//遍历value 24 { } 25 26 foreach (var de in dy) //同时遍历键/值对 27 { 28 Console.WriteLine(de.Key); 29 Console.WriteLine(de.Value); 30 } 31 dy.Clear();//清除全部 32 33 Console.Read(); 34 } 35 } 36 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Collections; 6 7 namespace Hashtable键值对集合 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 //个人感受他和Arrylist集合性质差很少,不分类型的存储 14 //键值是惟一的 15 Hashtable ht = new Hashtable(); 16 17 ht.Add("key1", "value1"); 18 19 ht.Add("key2", "value2"); 20 21 ht.Contains("key1");//判断key1键是否存在 22 23 ht.ContainsKey("key1");//同上 24 25 foreach (Object key in ht.Keys) //遍历key 26 { } 27 foreach (Object value in ht.Values)//遍历value 28 { } 29 30 foreach (DictionaryEntry de in ht) //同时遍历键/值对 31 { 32 Console.WriteLine(de.Key); 33 Console.WriteLine(de.Value); 34 } 35 36 37 /****************************/ 38 ht.Remove("key1");//移除key1键元素 39 40 //先后作个判断 41 Console.WriteLine(); 42 foreach (DictionaryEntry de in ht) //同时遍历键/值对 43 { 44 Console.WriteLine(de.Key); 45 Console.WriteLine(de.Value); 46 } 47 /********************************/ 48 49 50 51 /****************************/ 52 ht.Clear();//清除全部元素 53 54 //先后作个判断 55 Console.WriteLine(); 56 foreach (DictionaryEntry de in ht) //同时遍历键/值对 57 { 58 Console.WriteLine(de.Key); 59 Console.WriteLine(de.Value); 60 Console.WriteLine("这句话没输出就是键值对被清空了"); 61 } 62 63 64 Console.Read(); 65 } 66 } 67 }

1 using System;
2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 枚举 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 Console.WriteLine(Enum.GetName(typeof(Man), 1)); //仍是 刘备 (由值获取名字) 13 14 string[] array1 = Enum.GetNames(typeof(Man)); 15 Console.WriteLine(array1[1]); //关羽 16 17 Array array2 = Enum.GetValues(typeof(Man)); 18 Console.WriteLine(array2.GetValue(1)); //仍是关羽 19 20 Type t = Enum.GetUnderlyingType(typeof(Man)); 21 Console.WriteLine(t); //输出 Int32 22 23 //由值获取内容 24 int i = 1; 25 string Name = Enum.Parse(typeof(Man), i.ToString()).ToString(); //此时 Name="刘备" 26 Console.WriteLine(Name); 27 28 //由值获取内容 29 string Name2 = "关羽"; 30 int j = Convert.ToInt32(Enum.Parse(typeof(Man), Name2)); //此时 j=2 31 Console.WriteLine(j); 32 33 //这段是我本身写的。。。。(不是全都复制的) 34 //判断输入的字符串是否在枚举内 35 Console.WriteLine("请输入"); 36 string str = Console.ReadLine(); 37 bool b = Enum.IsDefined(typeof(Week), str); 38 39 Console.WriteLine(b.ToString()); 40 41 Console.ReadKey(); 42 } 43 } 44 45 enum Man 46 { 47 刘备 = 1, 48 关羽 = 2, 49 张飞 = 3 50 } 51 enum Week 52 { 53 Monday = 1, 54 Tuesday = 2, 55 Wednesday = 3, 56 Sunday = 0, 57 Everyday = 1 //成员的值能够设置成同样的,可是成员不行 58 } 59 enum sex : byte //显示指定枚举的底层数据类型 60 { 61 male, 62 female, //此逗号能够省略 63 }; //此分号能够省略 64 65 }
4.拆装箱

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Collections; 6 using System.Diagnostics; 7 8 //装箱操做和拆箱操做是要额外耗费cpu和内存资源的, 9 //因此用泛型来减小装箱操做和拆箱操做消耗。 10 namespace 拆箱_装箱 11 { 12 class Program 13 { 14 static void Main(string[] args) 15 { 16 int n1 = 10; 17 object o = n1;//装箱 18 int nn = (int)o;//拆箱 19 20 21 ArrayList lista = new ArrayList(); 22 List<int> list = new List<int>(); 23 //这个循环发生了100万次装箱操做 24 Stopwatch sw = new Stopwatch(); 25 sw.Start(); 26 for (int i = 0; i < 10000000; i++) 27 { 28 list.Add(i); 29 } 30 sw.Stop();//计时 31 Console.WriteLine(sw.Elapsed); 32 Console.ReadKey(); 33 34 35 //这个地方没有发生任意类型的装箱或者拆箱 36 string str = "123"; 37 int n2 = Convert.ToInt32(str); 38 39 40 int n3 = 10; 41 IComparable ic = n3;//装箱 42 43 } 44 } 45 }
5.逆变和协变

1 在网上收集的,平时感受不经常使用 2 咱们都知道.Net里或者说在OO的世界里,能够安全地把子类的引用赋给父类引用,例如: 3 4 //父类 = 子类 5 string str = "string"; 6 object obj = str;//变了 7 8 out 支持协变 9 in 支持逆变 10 11 协变(Foo<父类> = Foo<子类> ): (我的理解:object(范围大)=string(范围小)) 12 13 //泛型委托: 14 public delegate T MyFuncA<T>();//不支持逆变与协变 15 public delegate T MyFuncB<out T>();//支持协变 16 17 MyFuncA<object> funcAObject = null; 18 MyFuncA<string> funcAString = null; 19 MyFuncB<object> funcBObject = null; 20 MyFuncB<string> funcBString = null; 21 MyFuncB<int> funcBInt = null; 22 23 funcAObject = funcAString;//编译失败,MyFuncA不支持逆变与协变 24 funcBObject = funcBString;//变了,协变 25 funcBObject = funcBInt;//编译失败,值类型不参与协变或逆变 26 27 //泛型接口 28 public interface IFlyA<T> { }//不支持逆变与协变 29 public interface IFlyB<out T> { }//支持协变 30 31 IFlyA<object> flyAObject = null; 32 IFlyA<string> flyAString = null; 33 IFlyB<object> flyBObject = null; 34 IFlyB<string> flyBString = null; 35 IFlyB<int> flyBInt = null; 36 37 flyAObject = flyAString;//编译失败,IFlyA不支持逆变与协变 38 flyBObject = flyBString;//变了,协变 39 flyBObject = flyBInt;//编译失败,值类型不参与协变或逆变 40 41 //数组: 42 string[] strings = new string[] { "string" }; 43 object[] objects = strings; 44 45 ---------------------------------------------------------------------------------- 46 47 逆变(Foo<子类> = Foo<父类>)(我的理解:string(小范围)=object(大范围)) 48 49 public delegate void MyActionA<T>(T param);//不支持逆变与协变 50 public delegate void MyActionB<in T>(T param);//支持逆变 51 52 public interface IPlayA<T> { }//不支持逆变与协变 53 public interface IPlayB<in T> { }//支持逆变 54 55 MyActionA<object> actionAObject = null; 56 MyActionA<string> actionAString = null; 57 MyActionB<object> actionBObject = null; 58 MyActionB<string> actionBString = null; 59 actionAString = actionAObject;//MyActionA不支持逆变与协变,编译失败 60 actionBString = actionBObject;//变了,逆变 61 62 IPlayA<object> playAObject = null; 63 IPlayA<string> playAString = null; 64 IPlayB<object> playBObject = null; 65 IPlayB<string> playBString = null; 66 playAString = playAObject;//IPlayA不支持逆变与协变,编译失败 67 playBString = playBObject;//变了,逆变
6.工厂模式

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 //我的理解:工厂模式就是switch选择为核心,让用户本身选择要执行的方法(可是方法他是看不见的) 7 namespace 工厂模式 8 { 9 //第一步:先写抽象的父类 10 public abstract class All 11 { 12 public abstract void 上菜(); 13 } 14 //第二步:子类 重写父类方法 15 public class Gdfjdc : All 16 { 17 public override void 上菜() 18 { 19 Console.WriteLine("小二,上干豆腐卷大葱");//我是东北人 20 } 21 } 22 public class xcbdf : All 23 { 24 public override void 上菜() 25 { 26 Console.WriteLine("小二上小葱拌豆腐"); 27 } 28 } 29 public class xjdmg : All 30 { 31 public override void 上菜() 32 { 33 Console.WriteLine("小二上小鸡炖蘑菇"); 34 } 35 } 36 public class scy : All 37 { 38 public override void 上菜() 39 { 40 Console.WriteLine("小二上酸菜鱼"); 41 } 42 } 43 44 class Class1 45 { 46 //第三步:核心地方到了 switch选择 47 public static All GetUserStr(string str_user) 48 { 49 All db = null; 50 switch (str_user) 51 { 52 case "干豆腐卷大葱": db = new Gdfjdc(); 53 break; 54 case "小葱拌豆腐": db = new xcbdf(); 55 break; 56 case "小鸡炖蘑菇": db = new xjdmg(); 57 break; 58 case "酸菜鱼": db = new scy(); 59 break; 60 } 61 return db; 62 } 63 static void Main() 64 { 65 //开始用户选菜了 66 string str_user = Console.ReadLine(); 67 All db = GetUserStr(str_user); 68 db.上菜(); 69 70 Console.Read(); 71 } 72 } 73 }
7.部分类partial

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 部分类partial 7 { 8 partial class Program 9 { 10 static void Main(string[] args) 11 { 12 Print(); 13 Console.ReadKey(); 14 } 15 } 16 partial class Program 17 { 18 static string str = "我是大帅哥"; 19 } 20 21 partial class Program 22 { 23 public static void Print() 24 { 25 Console.WriteLine(str); 26 } 27 } 28 }
8.密封类sealed

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 密封类 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 Person.person(); 13 Test.test(); 14 15 Console.Read(); 16 } 17 } 18 //密封类用sealed关键字 19 // public static sealed class Person : Test//这是错误的!!类不能便是密封的又是静态static的 20 public sealed class Person : Test 21 { 22 public static void person() 23 { 24 Console.WriteLine("我是密封类"); 25 } 26 } 27 //public static class Test //这是错误的!!密封类不能继承于静态类 28 public class Test 29 { 30 public static void test() 31 { 32 Console.WriteLine("我是父类"); 33 } 34 } 35 //public class abc : Person { }//这是错误的!!密封类不能被继承 36 }
9.重写ToString方法

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 //首先要知道ToString是系统内部自有的方法 7 //系统内定义:public override string ToString(); 是个可被重写的方法 8 //这个例子不是简单的说明重写ToString,说明有不少系统定义的方法,咱们均可以拿来重写的 9 namespace 重写ToString方法 10 { 11 class Program 12 { 13 static void Main(string[] args) 14 { 15 Person p = new Person(); 16 Console.WriteLine(p.ToString()); 17 Console.ReadKey(); 18 } 19 } 20 21 public class Person 22 { 23 public override string ToString() 24 { 25 return "Hello World"; 26 } 27 } 28 }
10.属性

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 //看网上对属性的讲解: 7 //c#中为何要用属性,一、在给一个对象附值时,能够经过属性SET方法, 8 //对这个值进行一个过滤,看这个值服不服合属性的要求。二、有的对象的属性, 9 //须要只读的的,就能够省去SET方法,有的是只写的,就能够省去GET方法 10 11 //属性就是为了访问私有字段,也就是为了对私有字段进行封装 12 13 //公有属性是在任何外部类均可访问到的,若是有人不怀好意就会随意的修改的public字段, 14 //很危险的,可是若是改为private,就不能擅自修改,只能经过属性,而在属性里是能够 15 //加代码来判断别人付的值是否符合你的要求,不符合的能够直接拒绝赋值,这样就增长了安全性 16 namespace 属性 17 { 18 class Program 19 { 20 /// <summary> 21 /// 自动属性 22 /// </summary> 23 public int Age 24 { 25 get; 26 set; 27 } 28 29 //普通属性 30 private string _name; 31 32 public string Name 33 { 34 get { return _name; } 35 set { _name = value; } 36 } 37 38 static void Main(string[] args) 39 { 40 } 41 } 42 }
11.里氏转换is、as

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 //里氏转换 6 //一、子类能够复制给父类:若是有一个地方须要一个父类作参数,咱们能够给一个子类代替 7 //二、若是父类中装的是子类对象,那么咱们是能够将这个父类转换为子类对象的 8 9 namespace is_as 10 { 11 public class User 12 { 13 14 } 15 class Program 16 { 17 static void Main(string[] args) 18 { 19 Object obj1 = new User(); 20 //is:表示类型转换----若是转换成功,返回一个true,不然返回false 21 if (obj1 is User)//这里必定要知道object是一切类的父类,父类转子类判断是否成功 22 { 23 User user1 = (User)obj1;//将父类对象强制转换成子类对象 24 Console.WriteLine("转换成功"); 25 } 26 else 27 { 28 Console.WriteLine("转换失败"); 29 } 30 31 /****************************/ 32 33 Object obj2 = new User(); 34 //as:表示类型转换-----若是可以转换则返回一个对应的对象,不然返回一个null 35 User user2 = obj2 as User;//将父类对象强制转换成子类对象 36 if (user2 == null) 37 { 38 Console.WriteLine("转换失败"); 39 } 40 else 41 { 42 Console.WriteLine("转换成功"); 43 } 44 Console.ReadKey(); 45 } 46 } 47 }
12.接口
别人写的,注释写的很好,简单易懂

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 #region 介绍接口 7 //如要实现接口类中对应的成员必须是公共的、非静态的, 8 //而且与接口成员具备相同的名称和签名。 9 //而且接口的实例化不能像类那样Program program = new Program(); 10 //其中上述程序中红色部分即为接口的实例化(使用派生类对象实例化接口)。 11 //一、接口的概念及声明 12 13 //接口是一种用来定义程序的协议,它描述可属于任何类或结构的一组相关行为。接口可有方法、属性、事件和索引器或这四种成员的任何组合类型,但不能包含字段。 14 15 //那么接口具备哪些特色呢? 16 17 //·接口相似于抽象基类:继承接口的任何非抽象类型都必须实现接口的全部成员(说明:如类A继承接口B,那么A中必须实现B中定义的属性,方法等)。 18 19 //·不能直接实例化接口 20 21 //·接口能够包含事件、索引器、方法和属性 22 23 //·接口不包含方法的实现 24 25 //·类和接口能够从多个接口继承 26 27 //·接口自身能够继承多个接口 28 29 //在声明接口时除了Interface和接口名称是必须的,其余都是可选项。另可以使用new、public、protected、intenal和private等修饰符实现接口,但接口成员必须是公共的。 30 31 //二、接口的实现与继承 32 33 //声明实现接口的类时,须要在基类列表中包含类所实现的接口的名称。 34 #endregion 35 namespace 接口_单继承_ 36 { 37 interface ImyInterface 38 { 39 /// <summary> 40 /// 编号(可读可写) 41 /// </summary> 42 string ID 43 { 44 get; 45 set; 46 } 47 /// <summary> 48 /// 姓名(可读可写) 49 /// </summary> 50 string Name 51 { 52 get; 53 set; 54 } 55 /// <summary> 56 /// 显示定义的编号和姓名 57 /// </summary> 58 void ShowInfo(); 59 } 60 class Program : ImyInterface//继承自接口 61 { 62 string id = ""; 63 string name = ""; 64 /// <summary> 65 /// 编号 66 /// </summary> 67 public string ID 68 { 69 get 70 { 71 return id; 72 } 73 set 74 { 75 id = value; 76 } 77 } 78 /// <summary> 79 /// 姓名 80 /// </summary> 81 public string Name 82 { 83 get 84 { 85 return name; 86 } 87 set 88 { 89 name = value; 90 } 91 } 92 /// <summary> 93 /// 显示定义的编号和姓名 94 /// </summary> 95 public void ShowInfo() 96 { 97 Console.WriteLine("编号\t 姓名"); 98 Console.WriteLine(ID + "\t " + Name); 99 } 100 static void Main(string[] args) 101 { 102 Program program = new Program(); //实例化Program类对象 103 ImyInterface imyinterface = program; //使用派生类对象实例化接口ImyInterface 104 imyinterface.ID = "TM"; //为派生类中的ID属性赋值 105 imyinterface.Name = "C# 2.0从入门到应用开发"; //为派生类中的Name属性赋值 106 imyinterface.ShowInfo(); //调用派生类中方法显示定义的属性值 107 Console.ReadKey(); 108 } 109 } 110 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 多继承 7 { 8 interface IPeople 9 { 10 /// <summary> 11 /// 姓名 12 /// </summary> 13 string Name 14 { 15 get; 16 set; 17 } 18 /// <summary> 19 /// 性别 20 /// </summary> 21 string Sex 22 { 23 get; 24 set; 25 } 26 } 27 interface ITeacher : IPeople //继承公共接口 28 { 29 /// <summary> 30 /// 教学方法 31 /// </summary> 32 void teach(); 33 } 34 interface IStudent : IPeople //继承公共接口 35 { 36 /// <summary> 37 /// 学习方法 38 /// </summary> 39 void study(); 40 } 41 class Program : IPeople, ITeacher, IStudent//多接口继承 42 { 43 string name = ""; 44 string sex = ""; 45 /// <summary> 46 /// 姓名 47 /// </summary> 48 public string Name 49 { 50 get 51 { 52 return name; 53 } 54 set 55 { 56 name = value; 57 } 58 } 59 /// <summary> 60 /// 性别 61 /// </summary> 62 public string Sex 63 { 64 get 65 { 66 return sex; 67 } 68 set 69 { 70 sex = value; 71 } 72 } 73 /// <summary> 74 /// 教学方法 75 /// </summary> 76 public void teach() 77 { 78 Console.WriteLine(Name + " " + Sex + " 教师"); 79 } 80 /// <summary> 81 /// 学习方法 82 /// </summary> 83 public void study() 84 { 85 Console.WriteLine(Name + " " + Sex + " 学生"); 86 } 87 static void Main(string[] args) 88 { 89 Program program = new Program(); //实例化类对象 90 ITeacher iteacher = program; //使用派生类对象实例化接口ITeacher 91 iteacher.Name = "TM"; 92 iteacher.Sex = "男"; 93 iteacher.teach(); 94 IStudent istudent = program; //使用派生类对象实例化接口IStudent 95 istudent.Name = "C#"; 96 istudent.Sex = "男"; 97 istudent.study(); 98 Console.ReadKey(); 99 } 100 } 101 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 #region 7 //试想一下,若是在一个类A继承自接口B和C, 8 //而且在B和C中包含具备相同签名的成员, 9 //那么在类中实现该成员将致使两个接口都使用该成员做为他们的实现, 10 //然而,若是两个接口成员实现不一样的功能, 11 //那么将会致使一个接口的成员实现不正确或两个接口的成员实现都不正确, 12 //这个时候咱们应该如何处理呢?咱们能够显示的实现接口成员, 13 //即建立一个仅经过接口调用而且特定于该接口的类成员。 14 #endregion 15 namespace 显示实现接口成员 16 { 17 interface ImyInterface1 18 { 19 /// <summary> 20 /// 求和方法 21 /// </summary> 22 /// <returns>加法运算的和</returns> 23 int Add(); 24 } 25 interface ImyInterface2 26 { 27 /// <summary> 28 /// 求和方法 29 /// </summary> 30 /// <returns>加法运算的和</returns> 31 int Add(); 32 } 33 class myClass : ImyInterface1, ImyInterface2 //继承接口 34 { 35 /// <summary> 36 /// 求和方法 37 /// </summary> 38 /// <returns>加法运算的和</returns> 39 int ImyInterface1.Add() //显式接口成员实现 40 { 41 int x = 3; 42 int y = 5; 43 return x + y; 44 } 45 /// <summary> 46 /// 求和方法 47 /// </summary> 48 /// <returns>加法运算的和</returns> 49 int ImyInterface2.Add() //显式接口成员实现 50 { 51 int x = 3; 52 int y = 5; 53 int z = 7; 54 return x + y + z; 55 } 56 } 57 class Program 58 { 59 static void Main(string[] args) 60 { 61 myClass myclass = new myClass(); //实例化接口继承类的对象 62 ImyInterface1 imyinterface1 = myclass; //使用接口继承类的对象实例化接口 63 Console.WriteLine(imyinterface1.Add()); //使用接口对象调用接口中方法 64 ImyInterface2 imyinterface2 = myclass; //使用接口继承类的对象实例化接口 65 Console.WriteLine(imyinterface2.Add()); //使用接口对象调用接口中方法 66 Console.ReadKey(); 67 } 68 } 69 } 70 //上面的实例中在Myclass类中,经过两个显示接口成员的方法分别实现了两个接口中的Add方法,在实例化不一样的接口后,调用相应的方法实现输出结果。
13.接口与抽象类的区别

1 c#接口和抽象类的区别 2 3 你们都容易把这二者搞混,我也同样,在听李建忠老师的设计模式时,他也老把抽象类说成接口,弄的我就更糊涂了,因此找了些网上的资料. 4 1、抽象类: 5 抽象类是特殊的类,只是不能被实例化;除此之外,具备类的其余特性;重要的是抽象类能够包括抽象方法,这是普通类所不能的。抽象方法只能声明于抽象类中,且不包含任何实现,派生类必须覆盖它们。另外,抽象类能够派生自一个抽象类,能够覆盖基类的抽象方法也能够不覆盖,若是不覆盖,则其派生类必须覆盖它们。 6 7 8 2、接口: 9 接口是引用类型的,相似于类,和抽象类的类似之处有三点: 10 1、不能实例化; 11 2、包含未实现的方法声明; 12 3、派生类必须实现未实现的方法,抽象类是抽象方法,接口则是全部成员(不只是方法包括其余成员); 13 14 另外,接口有以下特性: 15 接口除了能够包含方法以外,还能够包含属性、索引器、事件,并且这些成员都被定义为公有的。除此以外,不能包含任何其余的成员,例如:常量、域、构造函数、析构函数、静态成员。一个类能够直接继承多个接口,但只能直接继承一个类(包括抽象类)。 16 17 3、抽象类和接口的区别: 18 1.类是对对象的抽象,能够把抽象类理解为把类看成对象,抽象成的类叫作抽象类.而接口只是一个行为的规范或规定,微软的自定义接口老是后带able字段,证实其是表述一类类“我能作。。。”.抽象类更多的是定义在一系列紧密相关的类间,而接口大多数是关系疏松但都实现某一功能的类中. 19 2.接口基本上不具有继承的任何具体特色,它仅仅承诺了可以调用的方法; 20 3.一个类一次能够实现若干个接口,可是只能扩展一个父类 21 4.接口能够用于支持回调,而继承并不具有这个特色. 22 5.抽象类不能被密封。 23 6.抽象类实现的具体方法默认为虚的,但实现接口的类中的接口方法却默认为非虚的,固然您也能够声明为虚的. 24 7.(接口)与非抽象类相似,抽象类也必须为在该类的基类列表中列出的接口的全部成员提供它本身的实现。可是,容许抽象类将接口方法映射到抽象方法上。 25 8.抽象类实现了oop中的一个原则,把可变的与不可变的分离。抽象类和接口就是定义为不可变的,而把可变的座位子类去实现。 26 9.好的接口定义应该是具备专注功能性的,而不是多功能的,不然形成接口污染。若是一个类只是实现了这个接口的中一个功能,而不得不去实现接口中的其余方法,就叫接口污染。 27 10.尽可能避免使用继承来实现组建功能,而是使用黑箱复用,即对象组合。由于继承的层次增多,形成最直接的后果就是当你调用这个类群中某一类,就必须把他们所有加载到栈中!后果可想而知.(结合堆栈原理理解)。同时,有心的朋友能够留意到微软在构建一个类时,不少时候用到了对象组合的方法。好比asp.net中,Page类,有Server Request等属性,但其实他们都是某个类的对象。使用Page类的这个对象来调用另外的类的方法和属性,这个是很是基本的一个设计原则。 28 11.若是抽象类实现接口,则能够把接口中方法映射到抽象类中做为抽象方法而没必要实现,而在抽象类的子类中实现接口中方法. 29 30 4、抽象类和接口的使用: 31 1. 若是预计要建立组件的多个版本,则建立抽象类。抽象类提供简单的方法来控制组件版本。 32 2.若是建立的功能将在大范围的全异对象间使用,则使用接口。若是要设计小而简练的功能块,则使用接口。 33 3.若是要设计大的功能单元,则使用抽象类.若是要在组件的全部实现间提供通用的已实现功能,则使用抽象类。 34 4.抽象类主要用于关系密切的对象;而接口适合为不相关的类提供通用功能。 35 36 如下是我在网上看到的几个形象比喻,真的很是不错,呵呵: 37 1.飞机会飞,鸟会飞,他们都继承了同一个接口“飞”;可是F22属于飞机抽象类,鸽子属于鸟抽象类。 38 2. 就像铁门木门都是门(抽象类),你想要个门我给不了(不能实例化),但我能够给你个具体的铁门或木门(多态);并且只能是门,你不能说它是窗(单继承);一个门能够有锁(接口)也能够有门铃(多实现)。 门(抽象类)定义了你是什么,接口(锁)规定了你能作什么(一个接口最好只能作一件事,你不能要求锁也能发出声音吧(接口污染))。
14.流操做

1 我的简单理解: 2 FileStream 操做字节的 3 StreamReader和StreamWriter 操做字符的 4 5 网络上的解释: 6 1. FileStream是一个较为底层的类,只能简单地读文件到缓存区,而StreamReader封装了一些高级方法如ReadLine() 7 2. FileStream可读可写,而StreamReader只能读不能写 8 3. FileStream不能指定编码(由于它看到的只是文件的二进制形式,固然无所谓编码),而StreamReader能够指定编码,一旦指定就不容许再更改,所以编码指定是放在它的构造方法里的。默认编码为System.Text.UTF8Encoding,实际上,在StreamReader的构造方法里,它会对文件进行编码检查,固然也能够不让它检查。 9 4. 若对是对二进制文件进行操做,最好使用BinaryReader,若要进行写操做,则用StreamWriter,一样StreamWriter也能按指定的编码进行读写 10 5. StreamReader的构造方法不必定须要FileStream,只须要文件名便可 11 6. StreamReader关闭后,与之相关的FileStream没有关闭,(经过FileStream的CanRead的测试) 12 13 FileStream对象表示在磁盘或网络路径上指向文件的流。这个类提供了在文件中读写字节的方法, 14 但常用StreamReader或StreamWriter执行这些功能。这是由于FileStream类操做的是字节和 15 字节数组,而Stream类操做的是字符数据。这是这两种类的一个重要区别,若是你是准备读取byte 16 数据的话,用StreamReader读取而后用System.Text.Encoding.Default.GetBytes转化的话,以下, 17 则可能出现数据丢失的状况,如byte数据的个数不对等。所以操做byte数据时要用FileStream。 18 19 string textContent = fileStream.ReadToEnd();byte[] bytes = System.Text.Encoding.Default.GetBytes(textContent); 20 字符数据易于使用,可是有些操做,好比随机文件访问(访问文件中间某点的数据),就必须由FileStream对象执行. 21 其中建立FileStream对象最简单的构造函数以下: 22 1FileStream file = newFileStream(fileName,FileMode.Member); 23 2FileStream file = newFileStream(fileName, FileMode.Member, FileAccess.Member);

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.IO; 6 7 namespace _StreamReader 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 //使用StreamReader来读取一个文本文件 14 //首先在\bin\Debug目录里(也就是程序运行的当前目录里要有new.txt文件),不然报错 15 using (StreamReader sr = new StreamReader(@"new.txt", Encoding.UTF8))//UTF8是一种读取的格式,还有其余不少种格式 16 { 17 while (!sr.EndOfStream) 18 { 19 Console.WriteLine(sr.ReadLine()); 20 } 21 } 22 Console.ReadKey(); 23 } 24 } 25 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.IO; 6 //FileStream 操做字节的 7 //StreamReader和StreamWriter 操做字符的 8 namespace _StreamWriter 9 { 10 class Program 11 { 12 static void Main(string[] args) 13 { 14 //使用StreamWriter来写入一个文本文件 15 //首先在\bin\Debug目录里(也就是程序运行的当前目录里要有new.txt文件),不然报错 16 using (StreamWriter sw = new StreamWriter(@"new.txt", true)) 17 { 18 sw.Write("看我有木有把你覆盖掉"); 19 } 20 Console.WriteLine("OK"); 21 Console.ReadKey(); 22 } 23 } 24 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.IO; 6 7 namespace 文件流 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 //使用FileStream来读取数据 14 FileStream fsRead = new FileStream(@"bxs.txt", FileMode.OpenOrCreate, FileAccess.Read); 15 byte[] buffer = new byte[1024 * 1024 * 5]; 16 //2.84K 5M 17 //返回本次实际读取到的有效字节数 18 int r = fsRead.Read(buffer, 0, buffer.Length); 19 //将字节数组中每个元素按照指定的编码格式解码成字符串 20 string s = Encoding.Default.GetString(buffer, 0, r); 21 //关闭流 22 fsRead.Close(); 23 //释放流所占用的资源 能够使用using替代它 24 fsRead.Dispose(); 25 Console.WriteLine(s); 26 Console.ReadKey(); 27 } 28 } 29 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.IO; 6 7 namespace 写入文件 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 //使用FileStream来写入数据 14 using (FileStream fsWrite = new FileStream(@"new.txt", FileMode.OpenOrCreate, FileAccess.Write)) 15 { 16 string str = "看我有没有把你覆盖掉"; 17 byte[] buffer = Encoding.UTF8.GetBytes(str); 18 fsWrite.Write(buffer, 0, buffer.Length); 19 } 20 Console.WriteLine("写入OK"); 21 Console.ReadKey(); 22 } 23 } 24 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.IO; 6 7 namespace 文件流拷贝多媒体文件 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 //思路:就是先将要复制的多媒体文件读取出来,而后再写入到你指定的位置 14 string source = @"abc.wmv"; 15 string target = @"new.wmv"; 16 CopyFile(source, target); 17 Console.WriteLine("复制成功"); 18 Console.ReadKey(); 19 } 20 21 public static void CopyFile(string soucre, string target) 22 { 23 //一、咱们建立一个负责读取的流 24 using (FileStream fsRead = new FileStream(soucre, FileMode.Open, FileAccess.Read)) 25 { 26 //二、建立一个负责写入的流 27 using (FileStream fsWrite = new FileStream(target, FileMode.OpenOrCreate, FileAccess.Write)) 28 { 29 byte[] buffer = new byte[1024 * 1024 * 5]; 30 //由于文件可能会比较大,因此咱们在读取的时候 应该经过一个循环去读取 31 while (true) 32 { 33 //返回本次读取实际读取到的字节数 34 int r = fsRead.Read(buffer, 0, buffer.Length); 35 //若是返回一个0,也就意味什么都没有读取到,读取完了 36 if (r == 0) 37 { 38 break; 39 } 40 fsWrite.Write(buffer, 0, r); 41 } 42 } 43 } 44 } 45 } 46 }
15.序列化、反序列化(XML和二进制)
首先看一下我生成的XML文件,这里我就不讲解XML文件格式是怎么写的,很简单

1 <?xml version="1.0"?> 2 3 -<ArrayOfPerson xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 4 5 6 -<Person> 7 8 <Name>毕毕</Name> 9 10 <MyProperty>23</MyProperty> 11 12 </Person> 13 14 15 -<Person> 16 17 <Name>丹丹</Name> 18 19 <MyProperty>22</MyProperty> 20 21 </Person> 22 23 </ArrayOfPerson>

1 序列化又称串行化,是.NET运行时环境用来支持用户定义类型的流化的机制。 2 其目的是以某种存储造成使自定义对象持久化,或者将这种对象从一个地方传输到另外一个地方。 3 4 .NET框架提供了两种种串行化的方式: 5 1、是使用BinaryFormatter进行串行化; 6 2、使用XmlSerializer进行串行化。 7 第一种方式提供了一个简单的二进制数据流以及某些附加的类型信息, 8 而第二种将数据流格式化为XML存储。 9 能够使用[Serializable]属性将类标志为可序列化的。若是某个类的元素不想被序列化, 10 1、能够使用[NonSerialized]属性来标志, 11 2、能够使用[XmlIgnore]来标志。 12 13 序列化意思指的是把对象的当前状态进行持久化,一个对象的状态在面向对象的程序中是由属性表示的, 14 因此序列化类的时候是从属性读取值以某种格式保存下来,而类的成员函数不会被序列化, 15 .net存在几种默认提供的序列化,二进制序列化,xml和json序列化会序列化全部的实例共有属性。

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.IO; 6 using System.Xml.Serialization; 7 8 namespace xml序列化_反序列化 9 { 10 class Program 11 { 12 static void Main(string[] args) 13 { 14 List<Person> listpers = new List<Person>(); 15 Person p1 = new Person("毕毕", 23); 16 Person p2 = new Person("丹丹", 22); 17 18 listpers.Add(p1); 19 listpers.Add(p2);//把类的实例添加到listpers泛型列表中 20 21 XmlSerializeMethod(listpers);//序列化成xml 22 // ReXmlSerializeMethod();//反序列化 23 24 Console.Read(); 25 } 26 27 //序列化一个泛型列表到xml 28 public static void XmlSerializeMethod(List<Person> listPers) 29 { 30 using (FileStream fs = new FileStream("序列化.xml", FileMode.OpenOrCreate)) 31 { 32 XmlSerializer xs = new XmlSerializer(typeof(List<Person>)); 33 xs.Serialize(fs, listPers); 34 35 Console.WriteLine("序列化.xml" + "序列化文件成功"); 36 } 37 } 38 //反序列化一个xml到泛型列表 39 public static void ReXmlSerializeMethod() 40 { 41 using (FileStream fs = new FileStream("序列化.xml", FileMode.Open)) 42 { 43 XmlSerializer xs = new XmlSerializer(typeof(List<Person>)); 44 List<Person> listpers = xs.Deserialize(fs) as List<Person>; 45 if (listpers != null) 46 { 47 for (int i = 0; i < listpers.Count; i++) 48 { 49 listpers[i].SayHi(); 50 } 51 } 52 53 } 54 } 55 } 56 57 [Serializable]// 表示要进行序列化 58 public class Person 59 { 60 public Person() { } 61 public Person(string name, int age) 62 { 63 this.name = name; 64 this.age = age; 65 } 66 private string name; 67 public string Name 68 { 69 get { return name; } 70 set { name = value; } 71 } 72 [NonSerialized]//表示下面的age不进行序列化 73 private int age; 74 75 public int MyProperty 76 { 77 get { return age; } 78 set { age = value; } 79 } 80 81 public void SayHi() 82 { 83 Console.WriteLine("你们好,我是{0},今年{1}岁", name, age); 84 } 85 86 } 87 }

1 using System;
2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.IO; 6 using System.Runtime.Serialization.Formatters.Binary; 7 8 //会生成.bin文件(二进制文件) 9 namespace 二进制序列化_反序列化 10 { 11 class Program 12 { 13 static void Main(string[] args) 14 { 15 List<Person> listPers = new List<Person>(); 16 Person per1 = new Person("毕毕", 18); 17 Person per2 = new Person("丹丹", 20); 18 listPers.Add(per1); 19 listPers.Add(per2); 20 21 SerializeMethod(listPers);//序列化 22 Console.WriteLine("序列化完成"); 23 24 //ReserializeMethod();//反序列化,使用反序列化时把序列化部分注释,反序列化打开 25 26 #region 输出 27 //输出: 由于age不被序列化,因此为0 28 //序列化完成 29 //你们好,我是毕毕,今年0岁 30 //你们好,我是丹丹,今年0岁 31 #endregion 32 33 Console.ReadKey(); 34 } 35 36 static void ReserializeMethod() 37 { 38 //反序列化 39 using (FileStream fs = new FileStream("二进制.bin", FileMode.Open)) 40 { 41 BinaryFormatter bf = new BinaryFormatter(); 42 List<Person> list = bf.Deserialize(fs) as List<Person>; 43 if (list != null) 44 { 45 for (int i = 0; i < list.Count; i++) 46 { 47 list[i].SayHi(); 48 } 49 } 50 } 51 } 52 53 static void SerializeMethod(List<Person> listPers) 54 { 55 //序列化 56 using (FileStream fs = new FileStream("二进制.bin", FileMode.OpenOrCreate)) 57 { 58 BinaryFormatter bf = new BinaryFormatter(); 59 bf.Serialize(fs, listPers); 60 } 61 } 62 63 } 64 65 [Serializable]// 表示要进行序列化 66 class Person 67 { 68 public Person(){} 69 public Person(string name, int age) 70 { 71 this.name = name; 72 this.age = age; 73 } 74 private string name; 75 public string Name 76 { 77 get { return name; } 78 set { name = value; } 79 } 80 [NonSerialized]//表示下面的age不进行序列化 81 private int age; 82 83 public int MyProperty 84 { 85 get { return age; } 86 set { age = value; } 87 } 88 89 public void SayHi() 90 { 91 Console.WriteLine("你们好,我是{0},今年{1}岁",name,age); 92 } 93 } 94 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 //少许属性的自动化操做手动添加几下固然是没有问题的,可是属性数量较多的时候敲起 7 //这些繁锁的代码能够困了,再说对扩展和维护性形成不少的不便,这时,就须要使用反射来实现了。 8 9 //为了方便查看,建议使用计时窗口。也能够节点查看 10 11 //了解了类的属性反射使用后,那么方法也是能够这样作的, 12 //即t.GetProperties()改成t.GetMethods(),操做方法同上。 13 namespace 反射 14 { 15 public class A 16 { 17 public int Property1 { get; set; } 18 } 19 class Program 20 { 21 static void Main() 22 { 23 A aa = new A(); 24 Type type = aa.GetType();//获取类型 25 // string aaname = aa.Name; //获取类型名 26 // string aafullname = aa.FullName; //获取命名空间 27 // Type stu1 = typeof(Student); 28 // Type stu = Type.GetType("反射.Student"); 29 System.Reflection.PropertyInfo propertyInfo = type.GetProperty("Property1"); 30 propertyInfo.SetValue(aa, 5, null);//给对应属性赋值.能够改为循环赋值 31 int value = (int)propertyInfo.GetValue(aa, null); 32 Console.WriteLine(value); 33 34 Console.Read(); 35 } 36 } 37 38 public class Student 39 { 40 public void Abc() 41 { 42 Console.WriteLine("无所谓啦,反正不用输出的"); 43 } 44 } 45 }
16.PropertyInfo反射

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 //少许属性的自动化操做手动添加几下固然是没有问题的,可是属性数量较多的时候敲起 7 //这些繁锁的代码能够困了,再说对扩展和维护性形成不少的不便,这时,就须要使用反射来实现了。 8 9 //为了方便查看,建议使用计时窗口。也能够节点查看 10 11 //了解了类的属性反射使用后,那么方法也是能够这样作的, 12 //即t.GetProperties()改成t.GetMethods(),操做方法同上。 13 namespace 反射 14 { 15 public class A 16 { 17 public int Property1 { get; set; } 18 } 19 class Program 20 { 21 static void Main() 22 { 23 A aa = new A(); 24 Type type = aa.GetType();//获取类型 25 // string aaname = aa.Name; //获取类型名 26 // string aafullname = aa.FullName; //获取命名空间 27 // Type stu1 = typeof(Student); 28 // Type stu = Type.GetType("反射.Student"); 29 System.Reflection.PropertyInfo propertyInfo = type.GetProperty("Property1"); 30 propertyInfo.SetValue(aa, 5, null);//给对应属性赋值.能够改为循环赋值 31 int value = (int)propertyInfo.GetValue(aa, null); 32 Console.WriteLine(value); 33 34 Console.Read(); 35 } 36 } 37 38 public class Student 39 { 40 public void Abc() 41 { 42 Console.WriteLine("无所谓啦,反正不用输出的"); 43 } 44 } 45 }
17.GUID编号

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 //GUID代码是不重复的编号 7 //有时能够使用GUID编号做为数据库的id值 8 //买商品时收款机打印的编号就是利用的GUID编号 9 namespace _13.GUID代码 10 { 11 class Program 12 { 13 static void Main(string[] args) 14 { 15 //产生一个不会重复的编号 16 Console.WriteLine(Guid.NewGuid().ToString()); 17 Console.WriteLine(Guid.NewGuid().ToString()); 18 Console.WriteLine(Guid.NewGuid().ToString()); 19 Console.WriteLine(Guid.NewGuid().ToString()); 20 Console.WriteLine(Guid.NewGuid().ToString()); 21 Console.ReadKey(); 22 23 //这只是一次结果,每次都不同的 24 //c2ad2105-28c3-48cc-a550-ec6ecce7deba 25 //18881ad6-0cb9-49a5-b1c2-4747ccb3111c 26 //26c63df2-63f9-4d5b-8648-c6fd19d08c19 27 //a6b02a41-af88-4fd9-8b80-d14b4ef423d9 28 //3d8e93cb-5982-4b6f-bf63-33489929963a 29 } 30 } 31 }
18.StringBuilder

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 //String 在进行运算时(如赋值、拼接等)会产生一个新的实例, 8 //而 StringBuilder 则不会,StringBuilder会在内存中开辟一块 9 //连续的内存,当增长字符串其实是针对同一块内存的修改,因此效率更高。 10 //一字符串进行操做时最好使用 StringBuilder,不要使用 String 11 12 namespace _14_高效的StringBuilder 13 { 14 class Program 15 { 16 static void Main(string[] args) 17 { 18 StringBuilder sb = new StringBuilder(); 19 sb.Append("张三"); 20 sb.Append("李四"); 21 sb.Append("王五"); 22 sb.Append("李四"); 23 sb.Insert(1, 123); 24 sb.Replace("李四", "赵六");//把sb集合里的全部“李四”替换成赵六 25 sb.Replace("赵六", "七七"); 26 Console.WriteLine(sb.ToString()); 27 Console.ReadKey(); 28 } 29 } 30 }

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Windows.Forms; 10 11 //winform类型 12 namespace 使用StringBuilder来拼接网页 13 { 14 public partial class Form1 : Form 15 { 16 public Form1() 17 { 18 InitializeComponent(); 19 } 20 21 private void button1_Click(object sender, EventArgs e) 22 { 23 24 StringBuilder sb = new StringBuilder(); 25 sb.Append("<html>"); 26 sb.Append("<head>"); 27 sb.Append("</head>"); 28 sb.Append("<body>"); 29 sb.Append("<table border='1px' cellpadding='0px' cellspacing='0px'>"); 30 sb.Append("<tr>"); 31 sb.Append("<td>星期一</td>"); 32 sb.Append("<td>星期一</td>"); 33 sb.Append("<td>星期一</td>"); 34 sb.Append("<td>星期一</td>"); 35 sb.Append("</tr>"); 36 sb.Append("<tr>"); 37 sb.Append("<td>星期一</td>"); 38 sb.Append("<td>星期一</td>"); 39 sb.Append("<td>星期一</td>"); 40 sb.Append("<td>星期一</td>"); 41 sb.Append("</tr>"); 42 sb.Append("<tr>"); 43 sb.Append("<td>星期一</td>"); 44 sb.Append("<td>星期一</td>"); 45 sb.Append("<td>星期一</td>"); 46 sb.Append("<td>星期一</td>"); 47 sb.Append("</tr>"); 48 sb.Append("<tr>"); 49 sb.Append("<td>星期一</td>"); 50 sb.Append("<td>星期一</td>"); 51 sb.Append("<td>星期一</td>"); 52 sb.Append("<td>星期一</td>"); 53 sb.Append("</tr>"); 54 sb.Append("</table>"); 55 sb.Append("</body>"); 56 sb.Append("</html>"); 57 webBrowser1.DocumentText = sb.ToString();//这是添加了一个窗体空间,显示网页数据的 58 } 59 } 60 }
体现一下StringBuilder和String的差距,网上直接复制的一份对比程序

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Diagnostics; 6 7 //string类型的特别之处在于咱们能够像使用值类型那样使用string类型, 8 //而实际上string是引用类型。既然是引用类型,CLR就会把string类型保 9 //存在托管堆上。当咱们使用str1 = str1 + i.ToString();进行拼接,由 10 //于string类型的恒定性,不会改变str1在内存中的地址,而是在托管堆上 11 //建立了另一个字符串对象。如此,拼接10000次,就建立了10000个string 12 //类型对象,效率不免低下。 13 14 //而StringBuilder会在内存中开辟一块连续的内存,当增长字符串其实是 15 //针对同一块内存的修改,因此效率更高。 16 17 //固然,到底使用硬拼接字符串,仍是使用StringBuilder,不是绝对的,要 18 //看状况。当拼接字符串不多的状况下,固然直接硬拼接字符串就好了。 19 20 namespace StringBuilder和String比速度 21 { 22 class Program 23 { 24 static void Main(string[] args) 25 { 26 string str1 = string.Empty; 27 Stopwatch sw1 = new Stopwatch();//计时运行的时间 28 sw1.Start(); 29 for (int i = 0; i < 10000; i++) 30 { 31 str1 = str1 + i.ToString(); 32 } 33 sw1.Stop(); 34 Console.WriteLine("拼接字符串所耗费时间为:" + sw1.ElapsedMilliseconds + "毫秒"); 35 StringBuilder str2 = new StringBuilder(10000); 36 Stopwatch sw2 = new Stopwatch(); 37 sw2.Start(); 38 for (int i = 0; i < 10000; i++) 39 { 40 str2.Append(i.ToString()); 41 } 42 sw2.Stop(); 43 Console.WriteLine("使用StringBuilder所耗费时间为:" + sw2.ElapsedMilliseconds + "毫秒"); 44 Console.ReadKey(); 45 } 46 } 47 } 48 49 //运行结果: 50 //拼接字符串所耗费时间为:148毫秒 51 //使用StringBuilder所耗费时间为:1毫秒
19.委托

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 //我的理解概述: 7 //委托是C#内重重重点,都知道启动程序时必定会启动主线程,主线程按着顺序向下执行。 8 //在当点击一个控件须要执行一个以上的任务时,主线程就蒙了,仍是会继续工做可是界面“假死”。 9 //这是就要用到多线程,这个以后讲线程,c#是不容许跨线程的,这是委托就起到了做用。 10 //委托传值很方便,在以后就会发现委托和线程是个好基友。 11 //委托是有个好东西,他的好处我就不在这多说了,上网查查。 12 namespace delegate委托简单例子 13 { 14 class Program 15 { 16 public delegate void NAME(string nm);//定义委托,定义委托时传参类型要与对应的方法参数类型一致 17 public static NAME nm; //实例委托 18 19 //给委托传递须要的方法 20 public static void Name(string nm) 21 { 22 Console.WriteLine("My name is {0}", nm); 23 Console.ReadKey(); 24 } 25 26 static void Main(string[] args) 27 { 28 nm = new NAME(Name); 29 nm("毕小帅");//启动委托 30 } 31 } 32 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 泛型委托 7 { 8 class Program 9 { 10 public delegate void Del<T>(T item); 11 public static void Notify(int i) 12 { 13 Console.WriteLine("我是整数泛型委托"); 14 } 15 public static void Notify(string i) 16 { 17 Console.WriteLine("我是字符串泛型委托"); 18 } 19 20 static void Show(string str) 21 { 22 Console.WriteLine(str); 23 } 24 static string show(string str) 25 { 26 return str; 27 } 28 29 static void Main(string[] args) 30 { 31 Del<int> m1 = new Del<int>(Notify); 32 m1(1); 33 Del<string> m2 = new Del<string>(Notify); 34 m2(""); 35 36 Console.WriteLine(); 37 38 Action<string> str = Show;//Action 是系统提供的不具备返回值 39 str("我是毕毕"); 40 41 Console.WriteLine(); 42 43 Func<string,string> Str = show;//Func泛型具备返回值,Func内的第二个string是返回值类型 44 string ss = Str("我是小毕"); 45 Console.WriteLine(ss); 46 47 Console.ReadKey(); 48 } 49 } 50 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 匿名委托 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 List<string> names = new List<string>(); 13 names.Add("毕毕love丹丹"); 14 names.Add("毕毕"); 15 names.Add("丹丹"); 16 17 List<string> found = names.FindAll( //从前日后匹配相同字段 18 delegate(string name) 19 { 20 return name.StartsWith("毕毕", 21 StringComparison.OrdinalIgnoreCase); 22 }); 23 24 if (found != null) 25 { 26 foreach (string str in found) 27 Console.WriteLine(str); 28 } 29 Console.ReadKey(); 30 } 31 } 32 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace lamda 7 { 8 public delegate void Del1(); 9 public delegate void Del2(string name); 10 public delegate string Del3(string name); 11 12 class Program 13 { 14 static string n = "bb"; 15 16 static void Main(string[] args) 17 { 18 Del1 d1 = () => { Console.WriteLine("无参"+" "+"b1"); }; 19 20 Del2 d2 = (name) => { Console.WriteLine("无参"+" "+name); }; 21 22 Del3 d3 = (name) => { Console.WriteLine("return 返回的是"+name); return name; }; 23 24 d1(); d2(n); d3(n); 25 26 Console.ReadKey(); 27 } 28 } 29 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 多播委托 7 { 8 public delegate void Del(); 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 Del del = T1; 14 15 del += T2; 16 del += T3; 17 del += T4; 18 del(); 19 20 Console.ReadKey(); 21 } 22 23 public static void T1() 24 { 25 Console.WriteLine("我是T1"); 26 } 27 public static void T2() 28 { 29 Console.WriteLine("我是T2"); 30 } 31 public static void T3() 32 { 33 Console.WriteLine("我是T3"); 34 } 35 public static void T4() 36 { 37 Console.WriteLine("我是T4"); 38 } 39 } 40 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace class3 7 { 8 class Program 9 { 10 public delegate void Del(string name); 11 static void Main(string[] args) 12 { 13 ////Del del = new Del(Eat); 14 Del del = Eat1;//这俩种同样 15 del("毕小帅"); 16 17 Test("毕小帅", Eat1); 18 Test("丹丹", Eat2); 19 20 //匿名委托 21 Del d = delegate(string name) 22 { 23 Console.WriteLine("你好"+name); 24 }; 25 d("毕毕"); 26 27 //lamda表达式 => 28 Del dd = (string name) => { Console.WriteLine("hello" + name); }; 29 dd("小毕"); 30 31 Console.ReadKey(); 32 } 33 34 public static void Test(string name, Del del) 35 { 36 del(name); 37 } 38 39 public static void Eat1(string name) 40 { 41 Console.WriteLine(name+"吃了吗"); 42 } 43 public static void Eat2(string name) 44 { 45 Console.WriteLine(name + "吃了吗?"); 46 } 47 } 48 }

1 using System;
2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 委托事件 7 { 8 class Program 9 { 10 public delegate void SalaryCompute(); //声明一个代理类 11 12 public class Employee 13 { 14 public event SalaryCompute OnSalaryCompute; //定义事件,将其与代理绑定 15 16 public virtual void FireEvent() //触发事件的方法 17 { 18 if (OnSalaryCompute != null) 19 { 20 OnSalaryCompute(); //触发事件 21 } 22 } 23 } 24 25 public class HumanResource 26 { 27 public void SalaryHandler() //事件处理函数 28 { 29 Console.WriteLine("我可终于被打印出来了"); //只是打印一行字而已 30 } 31 32 public static void Main() 33 { 34 Employee ep = new Employee(); 35 HumanResource hr = new HumanResource(); 36 ep.OnSalaryCompute += new SalaryCompute(hr.SalaryHandler); //注册,委托链接到事件处理函数 37 ep.FireEvent(); //触发事件 38 Console.Read(); 39 } 40 } 41 } 42 }
收集一个类型不错的委托事件

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 事件练习 7 { 8 class Program 9 { 10 11 static void Main() 12 { 13 God.Start(); 14 } 15 /// <summary> 16 /// 类EatEventArgs 必须继承自类EventArgs,用来引起事件时封装数据 17 /// </summary> 18 public class EatEventArgs : EventArgs 19 { 20 public String restrauntName; //饭店名称 21 public decimal moneyOut; //准备消费金额 22 } 23 24 /// <summary> 25 /// 这个委托用来讲明处理吃饭事件的方法的方法头(模式) 26 /// </summary> 27 public delegate void EatEventHandler(object sender, EatEventArgs e); 28 29 /// <summary> 30 /// 引起吃饭事件(EateEvent)的类Master(主人),这个类必须 31 /// 1.声明一个名为EatEvent的事件: public event EatEventHandler EatEvent; 32 /// 2.经过一个名为OnEatEvent的方法来引起吃饭事件,给那些处理此事件的方法传数据; 33 /// 3.说明在某种情形下引起事件呢?在饿的时候。用方法Hungrg来模拟。 34 /// </summary> 35 public class Master 36 { 37 //声明事件 38 public event EatEventHandler EatEvent; 39 40 //引起事件的方法 41 public void OnEatEvent(EatEventArgs e) 42 { 43 if (EatEvent != null) 44 { 45 EatEvent(this, e); 46 } 47 } 48 49 //当主人饿的时候,他会指定吃饭地点和消费金额。 50 public void Hungry(String restrauntName, decimal moneyOut) 51 { 52 EatEventArgs e = new EatEventArgs(); 53 e.restrauntName = restrauntName; 54 e.moneyOut = moneyOut; 55 56 Console.WriteLine("主人说:"); 57 Console.WriteLine("我饿了,要去{0}吃饭,消费{1}元", e.restrauntName, e.moneyOut); 58 59 //引起事件 60 OnEatEvent(e); 61 } 62 } 63 64 /// <summary> 65 /// 类Servant(仆人)有一个方法ArrangeFood(安排食物)来处理主人的吃饭事件 66 /// </summary> 67 public class Servant 68 { 69 public void ArrangeFood(object sender, EatEventArgs e) 70 { 71 Console.WriteLine(); 72 Console.WriteLine("仆人说:"); 73 Console.WriteLine("个人主人, 您的命令是 : "); 74 Console.WriteLine("吃饭地点 -- {0}", e.restrauntName); 75 Console.WriteLine("准备消费 -- {0}元 ", e.moneyOut); 76 Console.WriteLine("好的,正给您安排。。。。。。。。\n"); 77 System.Threading.Thread.Sleep(5000); 78 Console.WriteLine("主人,您的食物在这儿,请慢用"); 79 Console.Read(); 80 } 81 } 82 83 /// <summary> 84 /// 类God安排qinshihuang(秦始皇)的仆人是lisi(李斯),并让李斯的ArrangeFood 85 /// 方法来处理qinshihuang的吃饭事件:qinshihuang.EatEvent += new EatEventHandler(lishi.ArrangeFood); 86 /// </summary> 87 public class God 88 { 89 public static void Start() 90 { 91 Master qinshihuang = new Master(); 92 Servant lishi = new Servant(); 93 94 qinshihuang.EatEvent += new EatEventHandler(lishi.ArrangeFood); 95 96 //秦始皇饿了,想去希尔顿大酒店,消费5000元 97 qinshihuang.Hungry("希尔顿大酒店", 5000.0m); 98 } 99 } 100 } 101 }
下面的是两个窗体简单传值(winform)

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 10 namespace 窗体传值 11 { 12 public partial class Form1 : Form 13 { 14 public Form1() 15 { 16 InitializeComponent(); 17 } 18 19 private void button1_Click(object sender, EventArgs e) 20 { 21 Form2 f2 = new Form2(Show); 22 f2.Show(); 23 } 24 25 void Show(string str) 26 { 27 label1.Text = str; 28 } 29 } 30 }

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 10 namespace 窗体传值 11 { 12 public delegate void Del(string str); //定义委托 13 14 public partial class Form2 : Form 15 { 16 public Del _del; 17 public Form2(Del del)//是将Form1里的Show()方法传过来了 18 { 19 this._del = del; //这个del能够想象成Form1窗体里的show(....)方法 20 InitializeComponent(); 21 } 22 //时钟 也能够写成while 都是一个效果 23 private void timer1_Tick(object sender, EventArgs e) 24 { 25 _del(textBox1.Text);//Form2窗体开启时Form1了的Show()方法就成为了 委托调用的方法 26 } 27 } 28 }

1 using System;
2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Diagnostics; 6 7 namespace 调用exe 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 //Process 是进程类 14 #region 这俩是同样的 15 Process.Start("notePad");//能够不加.exe =(notepad.exe) 16 //若是不是系统关联的程序指明路径就好了。 17 Process.Start(@"D:\Program Files (x86)\Tencent\QQ\Bin\QQ.exe");//这是个人qq安装路径 18 //我比较喜欢这个 19 Process p = Process.Start("notepad.exe"); 20 p.WaitForExit();//等待外部程序退出后才能往下执行 21 #endregion 22 23 #region 下面这俩是同样的 24 System.Diagnostics.Process exep = new System.Diagnostics.Process(); 25 exep.StartInfo.FileName = "notePad"; 26 exep.StartInfo.Arguments = @"C:\Users\Administrator\Desktop\字符串的知识"; 27 exep.StartInfo.CreateNoWindow = true; 28 exep.StartInfo.UseShellExecute = false; 29 exep.Start(); 30 exep.WaitForExit();//关键,等待外部程序退出后才能往下执行 31 //我喜欢这个 32 ProcessStartInfo startInfo = new ProcessStartInfo("IExplore.exe"); 33 startInfo.Arguments = "www.baidu.com";//启动参数 34 startInfo.WindowStyle = ProcessWindowStyle.Minimized; 35 Process.Start(startInfo); 36 #endregion 37 } 38 } 39 }
20.编写DLL文件、调用DLL文件、传参、返回值

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 //一.建立dll文件 6 // 1.在vs2010中建立Class Library 项目;(就是建个类) 7 // 2.在类中写上下面代码 8 // 3.3.按F6编译生成Dll文件 不要按别的!!按F6!!! 9 //二.调用dll文件(这步在新建的项目中) 10 namespace ClassLibrary1 11 { 12 public static class Class1 13 { 14 public static string Messages() 15 { 16 //定义了一个方法,此方法的做用就是返回下面字符串。 17 return "欢迎使用Visual Studio 2010 作的DLL文件!"; 18 } 19 static int s = 0; 20 public static int INT(int ii) 21 { 22 for (int i = 0; i < 10; i++) 23 { 24 s += ii; 25 } 26 return s; 27 } 28 } 29 }

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using System.Runtime.InteropServices; 10 using ClassLibrary1; 11 //二.调用dll文件 12 //将第一步生成的Dll文件(\bin\Debug\myFirstDll.dll)拷贝到新建的如今的项目文件夹下 13 //添加引用ClassLibrary1 14 //编辑代码(下面代码) 15 //编译运行 16 namespace 调用外部dll 17 { 18 public partial class Form1 : Form 19 { 20 public Form1() 21 { 22 InitializeComponent(); 23 } 24 25 [DllImport("user32.dll", EntryPoint = "MessageBoxA")] 26 27 static extern int MsgBox(int hWnd, string msg, string caption, int type); 28 private void button1_Click(object sender, EventArgs e) 29 { 30 MsgBox(0, " 这就是用 DllImport 调用 DLL 弹出的提示框哦! ", " 小毕毕 ", 0x30); 31 } 32 33 //调用本身写的dll文件 34 [DllImport("ClassLibrary1.dll")] 35 36 static extern string Messages();// 37 private void button2_Click(object sender, EventArgs e) 38 { 39 string str = Class1.Messages(); 40 MessageBox.Show(str); 41 } 42 43 [DllImport("ClassLibrary1.dll")] 44 45 static extern int INT(); 46 private void button3_Click(object sender, EventArgs e) 47 { 48 int s = Class1.INT(10); 49 MessageBox.Show(s.ToString()); 50 } 51 } 52 }
21.C# 操做XML

1 using System;
2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Xml; 7 namespace _03建立XML 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 //经过代码来建立XML文档 14 //一、引用命名空间 15 //二、建立XML文档对象 16 XmlDocument doc = new XmlDocument(); 17 //三、建立第一个行描述信息,而且添加到doc文档中 18 XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "utf-8", null); 19 doc.AppendChild(dec); 20 //四、建立根节点 21 XmlElement books = doc.CreateElement("Books"); 22 //将根节点添加到文档中 23 doc.AppendChild(books); 24 25 //五、给根节点Books建立子节点 26 XmlElement book1 = doc.CreateElement("Book"); 27 //将book添加到根节点 28 books.AppendChild(book1); 29 30 31 //六、给Book1添加子节点 32 XmlElement name1 = doc.CreateElement("Name"); 33 name1.InnerText = "毕毕"; 34 book1.AppendChild(name1); 35 36 XmlElement price1 = doc.CreateElement("Price"); 37 price1.InnerText = "10"; 38 book1.AppendChild(price1); 39 40 XmlElement des1 = doc.CreateElement("Des"); 41 des1.InnerText = "好看"; 42 book1.AppendChild(des1); 43 44 XmlElement book2 = doc.CreateElement("Book"); 45 books.AppendChild(book2); 46 47 48 XmlElement name2 = doc.CreateElement("Name"); 49 name2.InnerText = "毕毕"; 50 book2.AppendChild(name2); 51 52 XmlElement price2= doc.CreateElement("Price"); 53 price2.InnerText = "10"; 54 book2.AppendChild(price2); 55 56 XmlElement des2 = doc.CreateElement("Des"); 57 des2.InnerText = "好看"; 58 book2.AppendChild(des2); 59 60 doc.Save("Books.xml"); 61 Console.WriteLine("保存成功"); 62 Console.ReadKey(); 63 } 64 } 65 }

1 using System;
2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Xml; 7 namespace _4_建立带属性的XML文档 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 XmlDocument doc = new XmlDocument(); 14 XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "utf-8","yes"); 15 doc.AppendChild(dec); 16 17 XmlElement order = doc.CreateElement("Order"); 18 doc.AppendChild(order); 19 20 XmlElement customerName = doc.CreateElement("CustomerName"); 21 customerName.InnerXml = "<p>我是一个p标签</p>"; 22 order.AppendChild(customerName); 23 24 XmlElement customerNumber = doc.CreateElement("CustomerNumber"); 25 customerNumber.InnerText = "<p>我是一个p标签</p>"; 26 order.AppendChild(customerNumber); 27 28 29 XmlElement items = doc.CreateElement("Items"); 30 order.AppendChild(items); 31 32 XmlElement orderItem1 = doc.CreateElement("OrderItem"); 33 //给节点添加属性 34 orderItem1.SetAttribute("Name", "充气**");//嘿嘿 35 orderItem1.SetAttribute("Count", "10"); 36 items.AppendChild(orderItem1); 37 38 XmlElement orderItem2 = doc.CreateElement("OrderItem"); 39 //给节点添加属性 40 orderItem2.SetAttribute("Name", "充气**"); 41 orderItem2.SetAttribute("Count", "10"); 42 items.AppendChild(orderItem2); 43 44 XmlElement orderItem3 = doc.CreateElement("OrderItem"); 45 //给节点添加属性 46 orderItem3.SetAttribute("Name", "充气**"); 47 orderItem3.SetAttribute("Count", "10"); 48 items.AppendChild(orderItem3); 49 50 doc.Save("XML.xml"); 51 Console.WriteLine("保存成功"); 52 Console.ReadKey(); 53 54 55 } 56 } 57 }

1 using System;
2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Xml; 7 using System.IO; 8 namespace _5_追击XML 9 { 10 class Program 11 { 12 static void Main(string[] args) 13 { 14 //追加XML文档 15 XmlDocument doc = new XmlDocument(); 16 XmlElement books; 17 if (File.Exists("Books.xml")) 18 { 19 //若是文件存在 加载XML 20 doc.Load("Books.xml"); 21 //得到文件的根节点 22 books = doc.DocumentElement; 23 } 24 else 25 { 26 //若是文件不存在 27 //建立第一行 28 XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "utf-8", null); 29 doc.AppendChild(dec); 30 //建立跟节点 31 books = doc.CreateElement("Books"); 32 doc.AppendChild(books); 33 } 34 //五、给根节点Books建立子节点 35 XmlElement book1 = doc.CreateElement("Book"); 36 //将book添加到根节点 37 books.AppendChild(book1); 38 39 40 //六、给Book1添加子节点 41 XmlElement name1 = doc.CreateElement("Name"); 42 name1.InnerText = "c#开发大全"; 43 book1.AppendChild(name1); 44 45 XmlElement price1 = doc.CreateElement("Price"); 46 price1.InnerText = "110"; 47 book1.AppendChild(price1); 48 49 XmlElement des1 = doc.CreateElement("Des"); 50 des1.InnerText = "看不懂"; 51 book1.AppendChild(des1); 52 53 54 doc.Save("Books.xml"); 55 Console.WriteLine("保存成功"); 56 Console.ReadKey(); 57 58 } 59 } 60 }

1 using System;
2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Xml; 7 8 namespace _6_读取XML文档 9 { 10 class Program 11 { 12 static void Main(string[] args) 13 { 14 //比较综合点 15 XmlDocument doc = new XmlDocument(); 16 doc.Load("Books.xml"); 17 XmlNode root = doc.DocumentElement; 18 XmlNodeList nodeList = root.ChildNodes; 19 foreach (XmlNode node in nodeList) 20 { 21 Console.WriteLine(node.Name); 22 if (node.Name == "Book") 23 { 24 //找到name节点,进行操做 25 XmlNodeList xnl = doc.SelectNodes("/Books/Book/Name"); 26 foreach (XmlNode nd in xnl) 27 { 28 Console.WriteLine(nd.InnerText); 29 } 30 } 31 } 32 Console.ReadKey(); 33 } 34 } 35 } 36 #region 在网上一位博客那里收集过来了,我看他的资料我才会xml操做。我所有复制下来了 37 //C#操做XML时,要引入命名空间using System.Xml 38 39 //获取根节点的方法: 40 //一、知道根节点名称: 41 //XmlNode root = xmlDoc.SelectSingleNode("根节点名称"); 42 //二、不知道根节点名称: 43 //XmlElement root = xmlDoc.DocumentElement; 44 //xml中node(节点)和element(元素)的区别(仍是不太明白) 45 //一、element是一个小范围的定义,必须含有完整信息的结点才能叫作元素。例如:<div>内容</div>,一个元素必定是一个节点,一个节点不必定是一个元素。 46 //二、node是基本对象,attribute,element,text等都是node的子对象。 47 //建立节点 48 //一、CreateElement() 方法 49 //有一个参数,两个参数,三个参数三种重载,参数类型均为string。 50 //一个参数:CreateElement("元素名称") 51 //两个参数:CreateElement("元素名称","元素的命名空间") 52 //三个参数:CreateElement("元素的前缀","元素的名称","元素的命名空间") 53 //二、CreateNode() 方法 54 //三个参数 都为string类型 55 //CreateNode("节点类型","节点名称","节点命名空间") 56 //四个参数 都为string类型 57 //CreateNode("节点类型","节点的前缀","节点名称","节点命名空间") 58 //问题:节点前缀有什么做用?结点命名空间有什么做用? 59 //增长节点: 60 //一、AppendChild() 方法 61 //二、InsertAfter(要插入的节点,参考节点) 方法 62 //三、InsertBefore(要插入的节点,参考节点) 方法 63 //增长节点属性: 64 //SetAttribute("属性名","属性值")方法 65 66 //删除节点属性: 67 //RemoveAttribute("属性名称") 68 //给节点添加数据: 69 //一、给节点的innerText赋值 70 //例子:XmlElement eName = doc.CreateElement("name"); 71 // eName.InnerText = aaaaa; 72 //二、添加XmlText节点,为其添加值 73 // 添加节点元素 74 // 将XmlText以子节点的方式添加给节点元素 75 //例子: XmlElement eName = xmlDoc.CreateElement("name"); 76 // XmlText tName = xmlDoc.CreateTextNode(aaaaa); 77 // eName.AppendChild(tName); 78 //寻找某个节点(寻找name节点): 79 //先找到根节点,找出根节点下的节点列表(XmlNodeList),遍历每一个节点。 80 //再找每一个节点下的节点列表,进行遍历,指导找到所须要的节点。 81 //<msg> 82 //<name></name> 83 //<content></content> 84 //</msg> 85 //方法: 86 //XmlNode root = xmlDoc.SelectSingleNode("msg"); 87 //XmlNodeList nodeList = root.ChildNodes; 88 //foreach (XmlNode node in nodeList) 89 //{ 90 // if(node.Name=="name") 91 // { 92 // 找到name节点,进行操做 93 // } 94 //} 95 //删除节点 96 //RemoveAll(无参数) 97 //RemoveChild(要移除的节点) 98 //更新节点 99 //一、ReplaceChild(新节点,老节点) 100 //创建一个新节点,替换老节点 101 //二、找到要更新的节点,从新设置其属性和数据 102 //用GridView显示xml文件中的数据 103 //view plaincopy to clipboardprint? 104 //DataSet ds = new DataSet(); 105 //ds.ReadXml(Server.MapPath("BooksInfo.xml")); 106 //GridView1.DataSource = ds.Tables[0]; 107 //GridView1.DataBind(); 108 //DataSet ds = new DataSet(); 109 //ds.ReadXml(Server.MapPath("BooksInfo.xml")); 110 //GridView1.DataSource = ds.Tables[0]; 111 //GridView1.DataBind(); 112 //xml文件 113 //view plaincopy to clipboardprint? 114 //<?xml version="1.0" encoding="utf-8"?> 115 //<bookstore> 116 // <book genre="ee" ISBN="2-3631-4"> 117 // <title>三国演义</title> 118 // <author>lfdfd</author> 119 // <price>55.95</price> 120 // </book> 121 // <book ISBN="2-3631-4"> 122 // <title>CS从入门到精通</title> 123 // <author>涨红</author> 124 // <price>58.3</price> 125 // </book> 126 // <book genre="计算机" ISBN="2-3631-4"> 127 // <title>CS从入门到精通</title> 128 // <author>盖茨</author> 129 // <price>58.3</price> 130 // </book> 131 // <book genre="计算机" ISBN="2-3631-4"> 132 // <title>CS从入门到精通</title> 133 // <author>盖茨</author> 134 // <price>58.3</price> 135 // </book> 136 //</bookstore> 137 //<?xml version="1.0" encoding="utf-8"?> 138 //<bookstore> 139 // <book genre="ee" ISBN="2-3631-4"> 140 // <title>三国演义</title> 141 // <author>lfdfd</author> 142 // <price>55.95</price> 143 // </book> 144 // <book ISBN="2-3631-4"> 145 // <title>CS从入门到精通</title> 146 // <author>涨红</author> 147 // <price>58.3</price> 148 // </book> 149 // <book genre="计算机" ISBN="2-3631-4"> 150 // <title>CS从入门到精通</title> 151 // <author>盖茨</author> 152 // <price>58.3</price> 153 // </book> 154 // <book genre="计算机" ISBN="2-3631-4"> 155 // <title>CS从入门到精通</title> 156 // <author>盖茨</author> 157 // <price>58.3</price> 158 // </book> 159 //</bookstore> 160 //显示效果: 161 162 //删除属性为计算机的节点 163 //view plaincopy to clipboardprint? 164 //XmlDocument xmlDoc = new XmlDocument(); 165 //xmlDoc.Load(Server.MapPath("xml/BooksInfo.xml")); 166 //XmlNodeList xnl = xmlDoc.SelectSingleNode("bookstore").ChildNodes; 167 //foreach (XmlNode xn in xnl) 168 // { 169 // XmlElement xe = (XmlElement)xn; 170 171 // if (xe.GetAttribute("genre") == "计算机") 172 // { 173 // xe.RemoveAll();//删除属性=计算机的该节点的所有内容 174 // //xe.ParentNode.RemoveChild(xe); 175 // } 176 177 178 // } 179 //xmlDoc.Save(Server.MapPath("xml/BooksInfo.xml")); 180 //XmlDocument xmlDoc = new XmlDocument(); 181 //xmlDoc.Load(Server.MapPath("xml/BooksInfo.xml")); 182 //XmlNodeList xnl = xmlDoc.SelectSingleNode("bookstore").ChildNodes; 183 //foreach (XmlNode xn in xnl) 184 // { 185 // XmlElement xe = (XmlElement)xn; 186 // if (xe.GetAttribute("genre") == "计算机") 187 // { 188 // xe.RemoveAll();//删除属性=计算机的该节点的所有内容 189 // //xe.ParentNode.RemoveChild(xe); 190 // } 191 192 // } 193 //xmlDoc.Save(Server.MapPath("xml/BooksInfo.xml")); 194 //xe.ParentNode.RemoveChild(xe) 195 //寻找到xe节点的父节点,再删除他的子节点。那么此节点(包括节点标记)将不存在。显示中将没有空行 196 //xe.RemoveAll() 197 //移除节点内容,可是节点标签还在。显示中有空行 198 199 #endregion 200 201 #region 202 //读取xml节点内的数据内容 203 //XmlDocument doc = new XmlDocument(); 204 ////加载要读取的XML 205 //doc.Load("Order.xml"); 206 ////得到根节点 207 //XmlElement books = doc.DocumentElement; 208 ////得到子节点 返回节点的集合 209 //XmlNodeList xnl = books.ChildNodes; 210 //foreach (XmlNode item in xnl) 211 //{ 212 // Console.WriteLine(item.InnerText); 213 //} 214 //Console.ReadKey(); 215 216 217 ////读取带属性的XML文档 218 //XmlDocument doc = new XmlDocument(); 219 //doc.Load("Order.xml"); 220 //XmlNodeList xnl = doc.SelectNodes("/Order/Items/OrderItem"); 221 222 //foreach (XmlNode node in xnl) 223 //{ 224 // Console.WriteLine(node.Attributes["Name"].Value); 225 // Console.WriteLine(node.Attributes["Count"].Value); 226 //} 227 //Console.ReadKey(); 228 229 230 //改变属性的值 231 //XmlDocument doc = new XmlDocument(); 232 //doc.Load("Order.xml"); 233 //XmlNode xn = doc.SelectSingleNode("/Order/Items/OrderItem[@Name='190']"); 234 //xn.Attributes["Count"].Value = "200"; 235 //xn.Attributes["Name"].Value = "颜世伟"; 236 //doc.Save("Order.xml"); 237 //Console.WriteLine("保存成功"); 238 239 240 //删除相应的的范围 241 //XmlDocument doc = new XmlDocument(); 242 //doc.Load("Order.xml"); 243 //XmlNode xn = doc.SelectSingleNode("/Order/Items"); 244 //xn.RemoveAll(); 245 //doc.Save("Order.xml"); 246 //Console.WriteLine("删除成功"); 247 //Console.ReadKey(); 248 249 250 ////得到文档的根节点 251 //XmlDocument doc = new XmlDocument(); 252 //doc.Load("Books.xml"); 253 //XmlNode root = doc.DocumentElement; 254 //XmlNodeList nodeList = root.ChildNodes; 255 //foreach (XmlNode node in nodeList) 256 //{ 257 // Console.WriteLine(node.Name); 258 // //if(node.Name=="name") 259 // //{ 260 // // //找到name节点,进行操做 261 // //} 262 //} 263 264 265 ////比较综合点 266 //XmlDocument doc = new XmlDocument(); 267 //doc.Load("Order.xml"); 268 //XmlNode root = doc.DocumentElement; 269 //XmlNodeList nodeList = root.ChildNodes; 270 //foreach (XmlNode node in nodeList) 271 //{ 272 // Console.WriteLine(node.Name); 273 // if (node.Name == "Items") 274 // { 275 // //找到name节点,进行操做 276 // XmlNodeList xnl = doc.SelectNodes("/Order/Items/OrderItem"); 277 // foreach (XmlNode nd in xnl) 278 // { 279 // Console.WriteLine(nd.Attributes["Name"].Value); 280 // Console.WriteLine(nd.Attributes["Count"].Value); 281 // } 282 // } 283 //} 284 #endregion
所须要的XML文件,放在运行程序的当前目录下

1 <?xml version="1.0" encoding="UTF-8"?> 2 3 -<Books> 4 5 6 -<Book> 7 8 <Name>c#开发大全</Name> 9 10 <Price>110</Price> 11 12 <Des>看不懂</Des> 13 14 </Book> 15 16 17 -<Book> 18 19 <Name>c#开发大全</Name> 20 21 <Price>110</Price> 22 23 <Des>看不懂</Des> 24 25 </Book> 26 27 28 -<Book> 29 30 <Name>c#开发大全</Name> 31 32 <Price>110</Price> 33 34 <Des>看不懂</Des> 35 36 </Book> 37 38 39 -<Book> 40 41 <Name>c#开发大全</Name> 42 43 <Price>110</Price> 44 45 <Des>看不懂</Des> 46 47 </Book> 48 49 </Books>

1 <?xml version="1.0" encoding="UTF-8"?> 2 3 -<Books> 4 5 6 -<Book> 7 8 <Name>c#开发大全</Name> 9 10 <Price>110</Price> 11 12 <Des>看不懂</Des> 13 14 </Book> 15 16 17 -<Book> 18 19 <Name>c#开发大全</Name> 20 21 <Price>110</Price> 22 23 <Des>看不懂</Des> 24 25 </Book> 26 27 </Books>
22.字符串大小写转换

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace class2 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 string[] names = { "abDC", "BYl" }; 13 Prot(names); 14 prot(names); 15 } 16 17 public static void Prot(string[] name) 18 { 19 for (int i = 0; i < name.Length; i++) 20 { 21 name[i] = name[i].ToUpper();//转大写 22 Console.WriteLine(name[i]); 23 } 24 // Console.ReadKey(); 25 } 26 27 public static void prot(string[] name) 28 { 29 for (int i = 0; i < name.Length; i++) 30 { 31 name[i] = name[i].ToLower(); 32 Console.WriteLine(name[i]); 33 } 34 Console.ReadKey(); 35 } 36 } 37 }
23.单例模式
简单的:

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 10 namespace Csharp_特点_单体模式 11 { 12 public partial class Form1 : Form 13 { 14 public Form1() 15 { 16 InitializeComponent(); 17 } 18 19 private void button1_Click(object sender, EventArgs e) 20 { 21 Form2 f2 = Form2.instance; 22 23 f2.Show(); 24 } 25 } 26 }

1 using System;
2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 10 namespace Csharp_特点_单体模式 11 { 12 public partial class Form2 : Form 13 { 14 private Form2() 15 { 16 InitializeComponent(); 17 } 18 //不要说C#太懒了,这叫智慧,嘿嘿 19 public static readonly Form2 instance = new Form2(); 20 } 21 22 //核心在这里 23 //public class Singleton 24 //{ 25 // private Singleton(){} 26 // public static readonly Singleton instance = new Singleton(); 27 //} 28 }
相比之下复杂一点点的:

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Windows.Forms; 10 11 namespace _2_单例模式 12 { 13 public partial class Form1 : Form 14 { 15 public Form1() 16 { 17 InitializeComponent(); 18 } 19 20 private void Form1_Load(object sender, EventArgs e) 21 { 22 this.IsMdiContainer = true;//指定当前窗体为父窗体 23 this.WindowState = FormWindowState.Maximized; //窗体加载时,窗体为最大化 24 } 25 26 private void button1_Click(object sender, EventArgs e) 27 { 28 Form2 frm2 = Form2.GetSingle(); 29 frm2.MdiParent = this;//指定父窗体 30 31 frm2.Show(); 32 } 33 } 34 }

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Windows.Forms; 10 11 namespace _2_单例模式 12 { 13 public partial class Form2 : Form 14 { 15 //全局惟一的单例 16 public static Form2 FrmSingle=null; 17 18 public Form2() 19 { 20 InitializeComponent(); 21 } 22 23 public static Form2 GetSingle() 24 { 25 if (FrmSingle == null) 26 { 27 FrmSingle = new Form2(); 28 } 29 return FrmSingle; 30 } 31 } 32 //核心就是 这个 33 //public class Singleton 34 // { 35 // private static Singleton _instance = null; 36 // private Singleton() { } 37 // public static Singleton CreateInstance() 38 // { 39 // if (_instance == null) 40 // { 41 // _instance = new Singleton(); 42 // } 43 // return _instance; 44 // } 45 // } 46 }
线程安全的单例模式

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 10 namespace _2.线程安全的单例模式Singleton 11 { 12 public partial class Form1 : Form 13 { 14 public Form1() 15 { 16 InitializeComponent(); 17 } 18 19 private void button1_Click(object sender, EventArgs e) 20 { 21 Form2 f2 = Form2.CI(); 22 f2.Show(); 23 } 24 } 25 }

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 10 namespace _2.线程安全的单例模式Singleton 11 { 12 public partial class Form2 : Form 13 { 14 private volatile static Form2 ins = null; 15 private static readonly object lockHelper = new object(); 16 private Form2() 17 { 18 InitializeComponent(); 19 } 20 21 public static Form2 CI() 22 { 23 if (ins == null) 24 { 25 lock (lockHelper) 26 { 27 if (ins == null) 28 ins = new Form2(); 29 } 30 } 31 return ins; 32 } 33 } 34 //第二种考虑了线程安全,不过有点烦,但绝对是正规写法,经典的一叉 35 //核心就是这个 36 //public class Singleton 37 //{ 38 // private volatile static Singleton _instance = null; 39 // private static readonly object lockHelper = new object(); 40 // private Singleton() { } 41 // public static Singleton CreateInstance() 42 // { 43 // if (_instance == null) 44 // { 45 // lock (lockHelper) 46 // { 47 // if (_instance == null) 48 // _instance = new Singleton(); 49 // } 50 // } 51 // return _instance; 52 // } 53 //} 54 }
24.文件、文件夹操做(path、File、Directory)

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using System.IO; 10 11 namespace 文件操做 12 { 13 public partial class Form1 : Form 14 { 15 public Form1() 16 { 17 InitializeComponent(); 18 } 19 20 private void Form1_Load(object sender, EventArgs e) 21 { 22 //这是控制台程序,我就写在这里方便理解 23 ////注意:这样是没有在桌面建立任何文件的 24 //string path = @"C:\Users\Administrator\Desktop\new.txt";//个人桌面 目录 25 //Console.WriteLine(Path.GetDirectoryName(path));//获得 文件目录 26 //Console.WriteLine(Path.ChangeExtension(path, "jpg"));//等到文件目录,改变文件格式 27 //Console.ReadKey(); 28 } 29 30 private void btnCreate_Click(object sender, EventArgs e) 31 { 32 //using System.IO; 33 File.Create(@"C:\Users\Administrator\Desktop\new.txt"); 34 MessageBox.Show("建立成功"); 35 } 36 37 private void btnCopy_Click(object sender, EventArgs e) 38 { 39 File.Copy(@"C:\Users\Administrator\Desktop\new.txt", @"C:\Users\Administrator\Desktop\abc.txt", true);//加上true能够覆盖源文件,不加 不可覆盖 40 MessageBox.Show("拷贝成功"); 41 } 42 43 private void btnMove_Click(object sender, EventArgs e) 44 { 45 //也能够用这种方式重命名 46 File.Move(@"C:\Users\Administrator\Desktop\new.txt", @"C:\Users\Administrator\Desktop\new_old.txt"); 47 MessageBox.Show("移动成功"); 48 } 49 50 private void btnDelete_Click(object sender, EventArgs e) 51 { 52 File.Delete(@"C:\Users\Administrator\Desktop\new_old.txt"); 53 MessageBox.Show("删除成功"); 54 } 55 56 //下面的是读取和写入操做,首先要肯定有目标文件就是须要使用的文件(在指定目录建个txt文件) 57 //我使用的是C:\Users\Administrator\Desktop\毕毕love丹丹.txt 58 //定义个全局变量 方便使用 59 public static string strTxt = @"C:\Users\Administrator\Desktop\毕毕love丹丹.txt"; 60 61 private void btnWriter_Click(object sender, EventArgs e) 62 { 63 //File类写入 64 //其实写入任何东西都是没用处的,都被下面的Write...给覆盖了 65 //想要看见本身输入的内容把WriteAllLines和WriteAllText两行注释掉就好了 66 string str = txtWR.Text; 67 byte[] buffer = Encoding.Default.GetBytes(str); 68 File.WriteAllBytes(strTxt, buffer); 69 70 File.WriteAllLines(strTxt, new string[] { "张三", "李四", "王五", "赵六" }); 71 72 File.WriteAllText(strTxt, "你们请叫我‘毕小帅’");//覆盖 73 74 File.AppendAllText(strTxt, "没有覆盖哟"); 75 76 MessageBox.Show("成功"); 77 } 78 79 private void btnReader_Click(object sender, EventArgs e) 80 { 81 txtWR.Text = ""; 82 //使用File类来读取数据 83 byte[] buffer = File.ReadAllBytes(strTxt); 84 string str = Encoding.UTF8.GetString(buffer, 0, buffer.Length); 85 txtWR.Text = str + '\n'; 86 87 //编码:把字符串以怎样形式存储为二进制 ASCII GBK GB2312 UTF-8 88 89 string[] str1 = File.ReadAllLines(strTxt, Encoding.Default); 90 for (int i = 0; i < str1.Length; i++) 91 { 92 txtWR.AppendText(str1[i]); 93 } 94 95 ////ReadAllLines和ReadAllText都是读取文件的全部行 96 ////不一样的是 第一个读取全部行的集合,第二个是读取文件内的整个的 所有的数据 97 //string str2 = File.ReadAllText(strTxt, Encoding.Default); 98 //txtWR.AppendText(str2); 99 } 100 } 101 }
25.超市管理系统(控制台应用程序)
先看一下输出结果:
须要的文件:

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 //我仿照一个培训老师写的教程、 7 namespace 超市管理系统 8 { 9 class Prm_main 10 { 11 static void Main(string[] args) 12 { 13 //为了方便理解,我把类名和方法名都写成了汉字,工做中不能够这样,建议写成简写英文 14 15 //不管作什么,首先把流程搞清楚 16 // 看要求: 17 // 四种商品--酱油、香蕉、手机、电脑 18 // 每种商品都在单独的货架上 19 // 每种商品都是有id、价格、名字 20 // 用户购买商品的优惠,如何打折。得出总价钱 21 //知道这些就够了,简单的管理系统就有思路了。(我感受我比那位培训老师都讲的仔细,嘿嘿) 22 23 //个人思路: 24 //一、用户要买东西首先须要有商品 25 //二、每一个商品要有id、价格、名字 26 //三、商品不可能在超市里是乱放的,要有分类 27 //四、而后就是用户购买了,按照买的个数*价格*打折 28 29 //思路很清晰了,开始写了 30 //1.建个商品的父类 封装商品的(id、价格、名字)---商品Father.cs 31 //2.写出四种商品的类 32 //3.商品肯定了,把商品放在规定的货架上--超市.cs 33 //4.商品所有搞定后,接下来就是客户购买了,先写个打折的父类(由于好几种打折的方式,来重写父类) 34 //5.实现打折的方式---打折_满减.cs 35 //6.实现打折的方式---打折_折扣率.cs 36 //7.还须要个不打折的付款---不打折.cs 37 //8.准备工做所有结束了,最后一步就是用户购物了 38 //好了所有搞定 39 /*******************************************************/ 40 41 //接下来就是用户购物了 42 43 用户购物 sm = new 用户购物(); 44 //展现货物 45 sm.展现货物(); 46 //跟用户交互 47 sm.用户交互(); 48 Console.ReadKey(); 49 } 50 } 51 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 超市管理系统 7 { 8 class 商品Father 9 { 10 public double Price 11 { 12 get; 13 set; 14 } 15 16 public string Name 17 { 18 get; 19 set; 20 } 21 22 public string ID 23 { 24 get; 25 set; 26 } 27 28 public 商品Father(string id, double price, string Name) 29 { 30 this.ID = id; 31 this.Price = price; 32 this.Name = Name; 33 } 34 } 35 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 超市管理系统 7 { 8 class 电脑 : 商品Father 9 { 10 public 电脑(string id, double price, string Name) 11 : base(id, price, Name) 12 { 13 14 } 15 } 16 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 超市管理系统 7 { 8 class 手机 : 商品Father 9 { 10 public 手机(string id, double price, string Name) 11 : base(id, price, Name) 12 { 13 14 } 15 } 16 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 超市管理系统 7 { 8 class 香蕉 : 商品Father 9 { 10 public 香蕉(string id, double price, string Name) 11 : base(id, price, Name) 12 { 13 14 } 15 } 16 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 超市管理系统 7 { 8 class 酱油 : 商品Father 9 { 10 public 酱油(string id, double price, string Name) 11 : base(id, price, Name) 12 { 13 14 } 15 } 16 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 超市管理系统 7 { 8 class 超市 9 { 10 List<List<商品Father>> list = new List<List<商品Father>>(); 11 12 /// <summary> 13 ///向用户展现货物 14 /// </summary> 15 public void 展现货物() 16 { 17 foreach (var item in list) 18 { 19 Console.WriteLine("咱们超市有:" + item[0].Name + "," + "\t" + "有" + item.Count + "个," + "\t" + "每一个" + item[0].Price + "元"); 20 } 21 } 22 //list[0]存储Acer电脑 23 //list[1]存储三星手机 24 //list[2]存储酱油 25 //list[3]存储香蕉 26 /// <summary> 27 /// 在建立仓库对象的时候 像仓库中添加货架 28 /// </summary> 29 public 超市() 30 { 31 list.Add(new List<商品Father>()); 32 list.Add(new List<商品Father>()); 33 list.Add(new List<商品Father>()); 34 list.Add(new List<商品Father>()); 35 } 36 /// <summary> 37 /// 进货 38 /// </summary> 39 /// <param name="strType">货物的类型</param> 40 /// <param name="count">货物的数量</param> 41 public void JinPros(string strType, int count) 42 { 43 for (int i = 0; i < count; i++) 44 { 45 switch (strType) 46 { 47 case "手机": list[0].Add(new 香蕉(Guid.NewGuid().ToString(), 1000, "手机")); 48 break; 49 case "电脑": list[1].Add(new 手机(Guid.NewGuid().ToString(), 2000, "电脑")); 50 break; 51 case "酱油": list[2].Add(new 酱油(Guid.NewGuid().ToString(), 10, "酱油")); 52 break; 53 case "香蕉": list[3].Add(new 电脑(Guid.NewGuid().ToString(), 50, "香蕉")); 54 break; 55 } 56 } 57 } 58 /// <summary> 59 /// 从仓库中提取货物 60 /// </summary> 61 /// <param name="strType"></param> 62 /// <param name="count"></param> 63 /// <returns></returns> 64 public 商品Father[] QuPros(string strType, int count) 65 { 66 商品Father[] pros = new 商品Father[count]; 67 for (int i = 0; i < pros.Length; i++) 68 { 69 switch (strType) 70 { 71 case "手机": 72 pros[i] = list[0][0]; 73 list[0].RemoveAt(0); 74 break; 75 case "电脑": pros[i] = list[1][0]; 76 list[1].RemoveAt(0); 77 break; 78 case "酱油": pros[i] = list[2][0]; 79 list[2].RemoveAt(0); 80 break; 81 case "香蕉": pros[i] = list[3][0]; 82 list[3].RemoveAt(0); 83 break; 84 } 85 } 86 return pros; 87 } 88 } 89 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 超市管理系统 7 { 8 /// <summary> 9 /// 打折的父类 抽象类---须要重写父类 10 /// </summary> 11 abstract class 打折Father 12 { 13 /// <summary> 14 /// 计算打折后应付多少钱 15 /// </summary> 16 /// <param name="realMoney">打折前应付的价钱</param> 17 /// <returns>打折后应付的钱</returns> 18 public abstract double 付钱(double realMoney); 19 } 20 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 超市管理系统 7 { 8 /// <summary> 9 /// 买M元 送N元 10 /// </summary> 11 class 打折_满减 : 打折Father 12 { 13 //买500送100 14 public double M 15 { 16 get; 17 set; 18 } 19 20 public double N 21 { 22 get; 23 set; 24 } 25 26 public 打折_满减(double m, double n) 27 { 28 this.M = m; 29 this.N = n; 30 } 31 public override double 付钱(double realMoney) 32 { 33 //600 -100 34 //1000-200 35 //1200 36 if (realMoney >= this.M) 37 { 38 return realMoney - (int)(realMoney / this.M) * this.N; 39 } 40 else 41 { 42 return realMoney; 43 } 44 } 45 } 46 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 超市管理系统 7 { 8 /// <summary> 9 /// 按折扣率打折 10 /// </summary> 11 class 打折_折扣率 : 打折Father 12 { 13 /// <summary> 14 /// 折扣率 15 /// </summary> 16 public double Rate 17 { 18 get; 19 set; 20 } 21 22 public 打折_折扣率(double rate) 23 { 24 this.Rate = rate; 25 } 26 public override double 付钱(double realMoney) 27 { 28 return realMoney * this.Rate; 29 } 30 31 } 32 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 超市管理系统 7 { 8 /// <summary> 9 /// 不打折 该多少钱就多少钱 10 /// </summary> 11 class 不打折 : 打折Father 12 { 13 public override double 付钱(double realMoney) 14 { 15 return realMoney; 16 } 17 } 18 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 超市管理系统 7 { 8 class 用户购物 9 { 10 //建立仓库对象 11 超市 ck = new 超市(); 12 /// <summary> 13 /// 建立超市对象的时候,给仓库的货架上导入货物 14 /// </summary> 15 public 用户购物() 16 { 17 ck.JinPros("酱油", 1000); 18 ck.JinPros("香蕉", 1000); 19 ck.JinPros("手机", 1000); 20 ck.JinPros("电脑", 1000); 21 } 22 23 /// <summary> 24 /// 跟用户交互的过程 25 /// </summary> 26 public void 用户交互() 27 { 28 Console.WriteLine("欢迎观临,请问您须要些什么?"); 29 Console.WriteLine("咱们有 酱油、香蕉、手机、电脑"); 30 string strType = Console.ReadLine(); 31 Console.WriteLine("您须要多少?"); 32 int count = Convert.ToInt32(Console.ReadLine()); 33 //去仓库取货物 34 商品Father[] pros = ck.QuPros(strType, count); 35 //下面该计算价钱了 36 double realMoney = 总价钱(pros); 37 Console.WriteLine("您总共应付{0}元", realMoney); 38 Console.WriteLine("请选择您的打折方式 1--不打折 2--打九折 3--打85 折 4--买300送50 5--买500送100"); 39 string input = Console.ReadLine(); 40 //经过简单工厂的设计模式根据用户的舒服得到一个打折对象 41 打折Father cal = 打折_工厂(input); 42 double totalMoney = cal.付钱(realMoney); 43 Console.WriteLine("打完折后,您应付{0}元", totalMoney); 44 Console.WriteLine("如下是您的购物信息"); 45 foreach (var item in pros) 46 { 47 Console.WriteLine("货物名称:" + item.Name + "," + "\t" + "货物单价:" + item.Price + "," + "\t" + "货物编号:" + item.ID); 48 } 49 } 50 51 /// <summary> 52 /// 根据用户的选择打折方式返回一个打折对象 53 /// </summary> 54 /// <param name="input">用户的选择</param> 55 /// <returns>返回的父类对象 可是里面装的是子类对象</returns> 56 public 打折Father 打折_工厂(string input) 57 { 58 打折Father cal = null; 59 switch (input) 60 { 61 case "1": cal = new 不打折(); 62 break; 63 case "2": cal = new 打折_折扣率(0.9); 64 break; 65 case "3": cal = new 打折_折扣率(0.85); 66 break; 67 case "4": cal = new 打折_满减(300, 50); 68 break; 69 case "5": cal = new 打折_满减(500, 100); 70 break; 71 } 72 return cal; 73 } 74 75 /// <summary> 76 /// 根据用户买的货物计算总价钱 77 /// </summary> 78 /// <param name="pros"></param> 79 /// <returns></returns> 80 public double 总价钱(商品Father[] pros) 81 { 82 double Money = 0; 83 //realMoney = pros[0].Price * pros.Length; 84 85 for (int i = 0; i < pros.Length; i++) 86 { 87 Money += pros[i].Price; 88 89 // realMoney = pros[i] * pros.Length; 90 } 91 return Money; 92 } 93 94 public void 展现货物() 95 { 96 ck.展现货物(); 97 } 98 } 99 }
26.小游戏(石头剪刀布)

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 10 namespace 石头剪刀布 11 { 12 public partial class Form1 : Form 13 { 14 public Form1() 15 { 16 InitializeComponent(); 17 // button1.Click += (s, e) => { shitou(); }; 18 button2.Click += (s, e) => { jiandao(); };//别忘了,事件只能出如今+=、-=左边 19 button3.Click += (d, e) => { bu(); }; 20 } 21 //其实button1.Click += (s, e) => { shitou(); };和下面的这写法是同样的 22 private void button1_Click(object sender, EventArgs e) 23 { 24 shitou(); 25 } 26 //石头 27 public void shitou() 28 { 29 label4.Text = button1.Text; 30 label3.Text = bj(toint(), pc()); 31 } 32 //剪刀 33 public void jiandao() 34 { 35 label4.Text = button2.Text; 36 label3.Text = bj(toint(), pc()); 37 } 38 39 //布 40 public void bu() 41 { 42 label4.Text = button3.Text; 43 label3.Text = bj(toint(), pc()); 44 } 45 46 /// <summary> 47 /// 电脑随机显示,还有相应的值替代它 48 /// </summary> 49 /// <returns></returns> 50 public int pc() 51 { 52 Random ran = new Random(); 53 int vpc = ran.Next(1, 4); 54 // string strpc;//这样写会浪费资源,在堆中要开辟不少空间 55 //这样,每次调用pc方法时strpc都是初始为空的。 56 //重要的是string类型是引用类型。 57 string strpc = string.Empty;//初始为空 58 switch (vpc) 59 { 60 case 1: 61 strpc = "石头"; 62 break; 63 case 2: 64 strpc = "剪刀"; 65 break; 66 case 3: 67 strpc = "布"; 68 break; 69 default: 70 throw new Exception("未知错误"); 71 } 72 label5.Text = strpc; 73 return vpc; 74 } 75 /// <summary> 76 /// 把剪刀石头布用数字表示 77 /// </summary> 78 /// <returns></returns> 79 public int toint() 80 { 81 int n; 82 switch (label4.Text) 83 { 84 case "石头": 85 n = 1; 86 break; 87 case "剪刀": 88 n = 2; 89 break; 90 case "布": 91 n = 3; 92 break; 93 default: 94 throw new Exception("出错了"); 95 } 96 return n; 97 } 98 //比较 99 public string bj(int user, int pc) 100 { 101 int tmp = user - pc; 102 string bj = string.Empty; 103 if (tmp == 1 || tmp == -2) 104 { 105 bj = "你输了"; 106 } 107 else if (tmp == 0) 108 { 109 bj = "平局"; 110 } 111 else 112 { 113 bj = "你赢了"; 114 } 115 return bj; 116 } 117 } 118 }
27.英汉词典

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using System.IO; 10 11 namespace 英汉词典 12 { 13 public partial class Form1 : Form 14 { 15 public Form1() 16 { 17 InitializeComponent(); 18 } 19 //第一步,我是先把英汉词典.txt数据源的内容储存起来,方便使用 20 //首先用一个泛型字典存储英汉词典.TXT里的内容 21 //检讨字典是(Dictionary<,>)这样的,里面是键值对 22 //每行数据必需要有一个惟一的键不能够重复,尾随的数据能够重复 23 24 //new 一个泛型字典 25 Dictionary<string, string> dic = new Dictionary<string, string>(); 26 //new 一个泛型list 27 List<string> list = new List<string>(); 28 29 //读取英汉词典.TXT文件,这就要知道它的路径了 30 //我我的建议是把英汉词典.txt文件放在相对路径下,由于打包以后方便使用 31 32 //绝对路径下读取文件 33 //加上@,便于后面的符号转换 34 //Encoding.Default是选择当前系统默认的字体编码 35 //string[] strarr = File.ReadAllLines(@"C:\Users\Administrator\Desktop\英汉词典.txt",Encoding.Default); 36 //相对路径下读取文件 37 //我选择的是相对路径 38 string[] strarr = File.ReadAllLines(@"英汉词典.txt", Encoding.Default); 39 40 //窗体加载时自动运行 41 private void Form1_Load(object sender, EventArgs e) 42 { 43 Stime(); 44 label2.Text = "您查询的结果:"; 45 label1.Text = ""; 46 47 //遍历每个行,每行都是两个元素,英文和中文 48 for (int i = 0; i < strarr.Length; i++) 49 { 50 //使用split方法移除单个空字符 51 string[] strarr1 = strarr[i].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); 52 //避免重复添加 53 //contains是包含的意思 54 if (!dic.Keys.Contains(strarr1[0])) 55 { 56 //其实这样也就能够了,可是做为一个严谨的程序员,我仍是给这一段加个判断 57 //将数组里的英文和中文填到泛型字典里 58 dic.Add(strarr1[0], strarr1[1]); 59 //将英文添加到泛型list里 60 //这样list内的数据都是dic内的键值 61 list.Add(strarr1[0]); 62 } 63 } 64 //为了让程序运行起来想过能高大上一些,就填了这一下的代码 65 AutoCompleteStringCollection strings = new AutoCompleteStringCollection(); 66 // 全部list泛型的英文单词转换成数组 添加到 strings里 67 strings.AddRange(list.ToArray()); 68 textBox1.AutoCompleteCustomSource = strings; //而后赋给文本框的 自动补全 所需的资源 属性 69 textBox1.AutoCompleteSource = AutoCompleteSource.CustomSource; //指定 CustomSource 为数据源 70 textBox1.AutoCompleteMode = AutoCompleteMode.Suggest; //启动自动补全模式 71 } 72 //以上读取英汉字典.txt的操做,已经搞定 73 //接下来就开始实现了 74 75 76 private void textBox1_TextChanged(object sender, EventArgs e) 77 { 78 //文本框内如果没有数据,就不显示label1 79 if (textBox1.Text == "") 80 { 81 label1.Text = ""; 82 } 83 84 //开始查找,文本框内与泛型字典键相同就把数据显示出来 85 //trim()是把空白的字符去掉 86 if (dic.Keys.Contains(textBox1.Text.Trim())) 87 { 88 //用键值找到数据,显示在textBox2中 89 textBox2.Text = dic[textBox1.Text.Trim()]; 90 91 //由于搜索到告终果,因此在线搜索不显示 92 linkLabel1.Visible = false; 93 label1.Text = ""; 94 label2.Text = "您查询的结果:"; 95 timer.Stop(); 96 Ltime = 0; 97 } 98 else if (textBox1.Text == "") 99 { 100 textBox2.Text = "请输入要查询单词"; 101 linkLabel1.Visible = false; 102 timer.Stop(); 103 Ltime = 0; 104 } 105 else 106 { 107 textBox2.Text = "正在搜索"; 108 //计时开始 109 timer.Start(); 110 label2.Text = "您查询的结果:"; 111 112 } 113 114 } 115 //以上显示部分也基本搞定 116 //对了,把在线查询实现出来 117 private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) 118 { 119 //由于我这有360浏览器,常常被终结,我就添加了try catch 120 try 121 { 122 System.Diagnostics.Process.Start("explorer.exe", "http://www.youdao.com/w/" + textBox1.Text.Trim()); 123 } 124 catch 125 { 126 MessageBox.Show("经过其余方式已将查询关闭"); 127 } 128 } 129 130 private void label2_Click(object sender, EventArgs e) 131 { 132 133 } 134 135 //为了让程序能高大上,我设置在20秒内如果没有查到结果就显示在线查找 136 //也能够按键盘回车键直接进行查询结果 137 138 //定义个查找所用时间 139 public int Ltime = 0; 140 //定义个计时器 141 public Timer timer; 142 143 public void Stime() 144 { 145 timer = new Timer(); 146 //一秒间隔 147 timer.Interval = 1000; 148 timer.Tick += (s, e) => 149 { 150 Ltime++; 151 label1.Text = Ltime.ToString();//显示查询几秒 152 153 if (Ltime >= 20) 154 { 155 label1.Text = "收索时间大于20秒已超时"; 156 label2.Text = "对不起,系统不包含您输入的单词"; 157 textBox2.Text = ""; 158 //显示网站连接 159 linkLabel1.Visible = true; 160 linkLabel1.Text = "对不起请尝试使用(有道youdao)在线翻译:" + "\r\n\n\t" + textBox1.Text.Trim(); 161 timer.Stop(); 162 Ltime = 0; 163 164 //使linkWebSearch控件显示的网址在textbox控件上面 165 linkLabel1.BringToFront(); 166 } 167 else//那就是20秒内显示出结果了 168 { 169 linkLabel1.Visible = false; 170 label1.Text = Ltime.ToString(); 171 } 172 }; 173 } 174 175 /// <summary> 176 /// 在textBox1文本框内点击回车的事件 177 /// </summary> 178 /// <param name="sender"></param> 179 /// <param name="e"></param> 180 private void textBox1_KeyDown(object sender, KeyEventArgs e) 181 { 182 //判断是否点击了回车按钮 183 if (e.KeyCode == Keys.Enter) 184 { 185 //我这是把上面的复制下来了,直接查出结果 186 if (dic.Keys.Contains(textBox1.Text.Trim())) 187 { 188 textBox2.Text = dic[textBox1.Text.Trim()]; 189 linkLabel1.Visible = false; 190 Ltime = 0; 191 label2.Text = "您查询的结果:"; 192 } 193 else 194 { 195 label2.Text = "对不起,系统不包含您输入的单词"; 196 label1.Text = ""; 197 textBox2.Text = ""; 198 199 linkLabel1.Visible = true; 200 201 linkLabel1.Text = "对不起请尝试使用(有道youdao)在线翻译:" + "\r\n\n\t" + textBox1.Text.Trim(); 202 203 timer.Stop(); 204 Ltime = 0; 205 linkLabel1.BringToFront(); 206 } 207 208 } 209 } 210 } 211 }
28.音乐播放器(winform)--------------这个软件会作了,才能表明C# winform开发 “基础”已经学会了
首先先上图片,了解一下软件的构造
ListBox控件属性要修改的地方
那些控件都好说,只要是播放控件vs上面没有:
这时,咱们就要手动添加,至关于调用了Windows的Dll文件了
一、在vs工具箱里右键点击“组件”(这是个人习惯,点击别的也能够)
二、找到“选择项”,点击。电脑通常配置的要等待一会,有点慢
三、看图
Form1主要部分:
Form2主要部分:
上代码了,接下来就本身对号入座吧

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using System.IO; 10 11 namespace 音乐播放器 12 { 13 public partial class Frm_main : Form 14 { 15 public Frm_main() 16 { 17 InitializeComponent(); 18 } 19 20 #region 加载窗体 21 private void Frm_main_Load(object sender, EventArgs e) 22 { 23 trackBar1.SendToBack();//置于底层 24 label1.Image = Image.FromFile("放音.jpg"); 25 label6.Text = "25"; 26 27 //trackBar1.BringToFront();//置于顶层 28 //trackBar2.BringToFront();//置于顶层 29 //程序加载时,取消播放器的自动播放 30 musicPlayer.settings.autoStart = false; 31 label1.Image = Image.FromFile("放音.jpg"); 32 //AutoEllipsis 属性能够改变 label控件的大小 33 toolTip1.SetToolTip(this.btn_PlayMode, "播放模式");//当鼠标放在控件上会显示 这是toolTip的功能 34 toolTip1.SetToolTip(this.label1, "声音开关");//当鼠标放在控件上会显示 这是toolTip的功能 35 } 36 #endregion 37 38 #region 窗体移动 39 bool formMoveFlag = false;//窗体是否移动标志位位 40 Point formPoint;//记录窗体的位置 41 /// <summary> 42 /// 鼠标在窗体上按下 43 /// </summary> 44 /// <param name="sender"></param> 45 /// <param name="e"></param> 46 private void MainForm_MouseDown(object sender, MouseEventArgs e) 47 { 48 formPoint = new Point(); 49 // int xOffset; 50 // int yOffset; 51 if (e.Button == MouseButtons.Left)//若是鼠标左键按下 52 { 53 formPoint = new Point(-e.X, -e.Y); //获得变量的值 54 formMoveFlag = true;//开始移动 55 } 56 } 57 /// <summary> 58 /// 鼠标在窗体上移动 59 /// </summary> 60 /// <param name="sender"></param> 61 /// <param name="e"></param> 62 private void MainForm_MouseMove(object sender, MouseEventArgs e) 63 { 64 if (formMoveFlag == true)//若是窗体正在移动 65 { 66 Point mousePos = Control.MousePosition;//获取鼠标当前位置 67 mousePos.Offset(formPoint.X, formPoint.Y);//设置鼠标移动后的位置 68 Location = mousePos;//将鼠标的坐标 传递给窗体 69 } 70 } 71 /// <summary> 72 /// 鼠标在窗体上释放 73 /// </summary> 74 /// <param name="sender"></param> 75 /// <param name="e"></param> 76 private void MainForm_MouseUp(object sender, MouseEventArgs e) 77 { 78 if (e.Button == MouseButtons.Left)//按下的是鼠标左键 79 { 80 formMoveFlag = false;//中止移动 81 } 82 } 83 #endregion 84 85 #region 一、主要的播放功能 86 87 //存储音乐文件的全路径 88 List<string> listpath = new List<string>(); 89 90 #region 右键 打开添加音乐文件 91 int addi = 0; 92 private void btn_Open_Click(object sender, EventArgs e) 93 { 94 OpenFileDialog ofd = new OpenFileDialog(); 95 ofd.InitialDirectory = @"音乐加歌词"; 96 ofd.Filter = "MP3文件|*.mp3|MP4文件|*.mp4|音乐文件|*.wav|全部文件|*.*"; 97 ofd.Title = "请选择音乐文件"; 98 ofd.Multiselect = true;//容许多选 99 ofd.ShowDialog(); 100 101 //得到文本框中选择文件的全路径 102 string[] path = ofd.FileNames; 103 for (int i = 0; i < path.Length; i++) 104 { 105 //将音乐文件的全路径加载到泛型集合中 106 addi++; 107 listpath.Add(path[i]); 108 //将音乐文件的文件名存储到ListBox中 109 lst_Playerfile.Items.Add(addi + "、" + Path.GetFileName(path[i])); 110 } 111 } 112 #endregion 113 #region 右键删除 114 private void 删除ToolStripMenuItem_Click(object sender, EventArgs e) 115 { 116 //删除的是列表中的选择项 117 //还要记住list集合也要删 118 119 //获取要删除的歌曲的数量 120 int count = lst_Playerfile.SelectedItems.Count; 121 for (int i = 0; i < count; i++) 122 { 123 //先删除集合 124 listpath.RemoveAt(lst_Playerfile.SelectedIndex); 125 //再删除表 126 lst_Playerfile.Items.RemoveAt(lst_Playerfile.SelectedIndex); 127 } 128 } 129 #endregion 130 #region 右键刷新 131 private void 刷新ToolStripMenuItem_Click(object sender, EventArgs e) 132 { 133 int add = 0; 134 List<string> lst = new List<string>(); 135 136 for (int i = 0; i < lst_Playerfile.Items.Count; i++) 137 { 138 add++; 139 //lst_Playerfile.Items.Add(add + "、" + lst_Playerfile.Items[i]); 140 string[] ss = lst_Playerfile.Items[i].ToString().Split('、'); 141 lst.Add(add + "、" + ss[1]); 142 } 143 lst_Playerfile.Items.Clear(); 144 foreach (var item in lst) 145 { 146 lst_Playerfile.Items.Add(item); 147 } 148 addi = add;//使刷新后的总行数等于addi,添加文件时能够正确排序 149 } 150 #endregion 151 152 #region ListBox的双击事件--选择播放的音乐 153 private void lst_Playerfile_DoubleClick(object sender, EventArgs e) 154 { 155 //timer3.Enabled = false; 156 //timer4.Enabled = false; 157 try 158 { 159 //索引找到点击播放的音乐是第几个 160 musicPlayer.URL = listpath[lst_Playerfile.SelectedIndex]; 161 musicPlayer.Ctlcontrols.play(); 162 IsExistLrc(listpath[lst_Playerfile.SelectedIndex]); 163 btn_Player.Text = "暂停"; 164 index_dq = lst_Playerfile.SelectedIndex; 165 } 166 catch { } 167 } 168 #endregion 169 170 #region 播放按钮 171 bool bl = true; 172 private void btn_Player_Click(object sender, EventArgs e) 173 { 174 try 175 { 176 if (bl) 177 { 178 musicPlayer.URL = listpath[lst_Playerfile.SelectedIndex]; 179 bl = false; 180 } 181 182 if (lst_Playerfile.SelectedIndex < 0) 183 { 184 MessageBox.Show("请选择播放的音乐文件"); 185 return; 186 } 187 if (btn_Player.Text == "播放") 188 { 189 //索引找到点击播放的音乐是第几个 190 //musicPlayer.URL = listpath[lst_Playerfile.SelectedIndex]; 191 musicPlayer.Ctlcontrols.play(); 192 //IsExistLrc(listpath[lst_Playerfile.SelectedIndex]); 193 IsExistLrc(musicPlayer.URL); 194 for (int i = 0; i < listpath.Count; i++) 195 { 196 if (musicPlayer.URL == listpath[i]) 197 { 198 index_dq = i; 199 } 200 } 201 //index_dq = lst_Playerfile.SelectedIndex; 202 //timer2.Enabled = true; 203 204 btn_Player.Text = "暂停"; 205 } 206 else if (btn_Player.Text == "暂停") 207 { 208 musicPlayer.Ctlcontrols.pause(); 209 btn_Player.Text = "播放"; 210 } 211 } 212 catch { } 213 } 214 #endregion 215 #region 终止播放 不是中止 216 private void btn_Stop_Click(object sender, EventArgs e) 217 { 218 musicPlayer.Ctlcontrols.stop(); 219 } 220 #endregion 221 #region 上一曲按钮 222 private void btn_Shang_Click(object sender, EventArgs e) 223 { 224 //try 225 // { 226 int index = lst_Playerfile.SelectedIndex; 227 lst_Playerfile.SelectedIndices.Clear(); 228 index--; 229 if (index < -1) 230 { 231 MessageBox.Show("选择播放文件"); 232 return; 233 } 234 else if (index < 0) 235 { 236 index = listpath.Count - 1; 237 musicPlayer.URL = listpath[index]; 238 } 239 musicPlayer.URL = listpath[index]; 240 lst_Playerfile.SelectedIndex = index; 241 musicPlayer.Ctlcontrols.play(); 242 IsExistLrc(listpath[lst_Playerfile.SelectedIndex]); 243 // } 244 // catch { MessageBox.Show("选择播放文件"); } 245 } 246 #endregion 247 #region 下一曲 248 private void btn_Xia_Click(object sender, EventArgs e) 249 { 250 //try 251 //{ 252 int index = lst_Playerfile.SelectedIndex; 253 lst_Playerfile.SelectedIndices.Clear(); 254 255 if (index < 0) 256 { 257 MessageBox.Show("选择播放文件"); 258 return; 259 } 260 index++; 261 if (index > listpath.Count - 1) 262 { 263 index = 0; 264 musicPlayer.URL = listpath[index]; 265 } 266 musicPlayer.URL = listpath[index]; 267 lst_Playerfile.SelectedIndex = index; 268 musicPlayer.Ctlcontrols.play(); 269 IsExistLrc(listpath[lst_Playerfile.SelectedIndex]); 270 //} 271 //catch { MessageBox.Show("选择播放文件"); } 272 } 273 #endregion 274 #region 声音开关按键 275 private void label1_Click(object sender, EventArgs e) 276 { 277 //将label的Tag属性设置为1 278 if (label1.Tag.ToString() == "1") 279 { 280 //目的让它静音 281 musicPlayer.settings.mute = true; 282 label1.Image = Image.FromFile("静音.jpg"); 283 label1.Tag = "2"; 284 label6.Text = "0";//显示音量大小 285 } 286 else if (label1.Tag.ToString() == "2") 287 { 288 //放音 289 musicPlayer.settings.mute = false; 290 label1.Image = Image.FromFile("放音.jpg"); 291 label1.Tag = "1"; 292 label6.Text = voice.ToString(); 293 } 294 } 295 #endregion 296 297 #region 模拟进度条--设置声音 298 int voice = 25; 299 //设置声音大小 300 public void setVoice(int voice) 301 { 302 if (voice >= 0 && voice <= 100) 303 { 304 musicPlayer.settings.volume = voice; 305 label6.Text = voice.ToString(); 306 } 307 } 308 private void panel5_MouseDown(object sender, MouseEventArgs e) 309 { 310 if (e.Location.X >= 0 && e.Location.X <= 100) 311 { 312 voice = e.Location.X; 313 panel5.Size = new Size(e.Location.X, 3); 314 setVoice(voice); 315 } 316 } 317 private void panel4_MouseDown(object sender, MouseEventArgs e) 318 { 319 if (e.Location.X >= 0 && e.Location.X <= 100) 320 { 321 voice = e.Location.X; 322 setVoice(voice); 323 panel5.Size = new Size(e.Location.X, 3); 324 } 325 } 326 #endregion 327 328 #region 计时器timer1--显示音乐时间、trackBar1显示播放进度 329 private void timer1_Tick(object sender, EventArgs e) 330 { 331 //若是播放器在播放中执行 332 if (musicPlayer.playState == WMPLib.WMPPlayState.wmppsPlaying) 333 { 334 label3.Text = musicPlayer.currentMedia.duration.ToString() + 335 "\r\n" + musicPlayer.currentMedia.durationString + 336 "\r\n" + musicPlayer.Ctlcontrols.currentPosition.ToString() + 337 "\r\n" + musicPlayer.Ctlcontrols.currentPositionString; 338 339 string[] sss1 = (musicPlayer.currentMedia.duration.ToString()).Split('.'); 340 string[] sss2 = (musicPlayer.Ctlcontrols.currentPosition.ToString()).Split('.'); 341 342 trackBar1.Maximum = int.Parse(sss1[0]); 343 trackBar1.Value = int.Parse(sss2[0]); 344 345 //if (Convert.ToInt32(label1.Tag) != 1)//当点击音乐开关时,label1.Tag=2; 346 //{ 347 // label6.Text = "0";//显示音量大小 348 //} 349 350 if (loob) 351 { 352 //自动下一曲 353 double d1 = double.Parse(musicPlayer.currentMedia.duration.ToString()); 354 355 double d2 = double.Parse(musicPlayer.Ctlcontrols.currentPosition.ToString()) + 1; 356 if (d1 <= d2) 357 { 358 //得到当前选中项的索引 359 int index = lst_Playerfile.SelectedIndex; 360 361 //清空全部选中项的索引 362 lst_Playerfile.SelectedIndices.Clear(); 363 index_dq++; 364 if (index_dq == lst_Playerfile.Items.Count) 365 { 366 index_dq = 0; 367 } 368 //将改变后的索引从新的赋值给当前选中项的索引 369 //if (index != index_dq) 370 //{ 371 // lst_Playerfile.SelectedIndex = index; 372 //} 373 //else 374 //{ 375 lst_Playerfile.SelectedIndex = index_dq; 376 //} 377 musicPlayer.URL = listpath[index_dq]; 378 musicPlayer.Ctlcontrols.play(); 379 IsExistLrc(listpath[index_dq]); 380 } 381 } 382 } 383 } 384 #endregion 385 386 #endregion 387 388 #region 二、歌词部分 389 390 //存储时间 391 List<double> listTime = new List<double>(); 392 //存储歌词 393 List<string> listLrcText = new List<string>(); 394 395 #region 添加歌词部分 396 //判断是否有歌词文件 397 void IsExistLrc(string songPath) 398 { 399 //清空两个集合的内容 400 listTime.Clear(); 401 listLrcText.Clear(); 402 403 songPath += ".lrc"; 404 if (File.Exists(songPath)) 405 { 406 //读取歌词文件 407 string[] lrcText = File.ReadAllLines(songPath, Encoding.Default); 408 //格式化歌词 409 FormatLrc(lrcText); 410 } 411 else//不存在歌词 412 { 413 label4.Text = "---------歌词未找到---------"; 414 415 Form2.StrLrc = label4.Text; 416 } 417 } 418 419 /// <summary> 420 /// 添加歌词 421 /// </summary> 422 /// <param name="lrcText"></param> 423 void FormatLrc(string[] lrcText) 424 { 425 for (int i = 0; i < lrcText.Length; i++) 426 { 427 //lrc格式歌词是这样的:[00:15.57]当我和世界不同 428 string[] lrcTemp = lrcText[i].Split(new char[] { '[', ']' }, StringSplitOptions.RemoveEmptyEntries); 429 //00:15.57 lrcTemp[0] 430 //当我和世界不同 lrcTemp[1] 431 string[] lrcNewTemp = lrcTemp[0].Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries); 432 //00 lrcNewTemp[0] 433 //15.57 lrcNewTemp[1] 434 double time = double.Parse(lrcNewTemp[0]) * 60 + double.Parse(lrcNewTemp[1]); 435 //把截取出来的时间加到泛型集合中 436 listTime.Add(time); 437 //把这个时间所对应的歌词存储到泛型集合中 438 try 439 { 440 listLrcText.Add(lrcTemp[1]); 441 } 442 catch { listLrcText.Add(lrcTemp[0]); } 443 } 444 } 445 #endregion 446 #region 计时器timer2---播放歌词 447 private void timer2_Tick(object sender, EventArgs e) 448 { 449 for (int i = 0; i < listTime.Count; i++)//listTime listLrcText都行 450 { 451 try 452 { 453 if (musicPlayer.Ctlcontrols.currentPosition >= listTime[i] && musicPlayer.Ctlcontrols.currentPosition < listTime[i + 1]) 454 { 455 label4.Text = listLrcText[i]; 456 Form2.StrLrc = listLrcText[i]; 457 } 458 } 459 catch { label4.Text = listLrcText[i]; } 460 } 461 } 462 #endregion 463 464 #endregion 465 466 #region 三、播放模式 467 468 #region 以前写的按钮点击事件 音量加减、快进快退、快退很差使,查了资料仍是不行,不知道是我写错了仍是mp3格式不支持 469 //音量加 470 //private void btn_YL_jia_Click(object sender, EventArgs e) 471 //{ 472 // musicPlayer.settings.volume += 5; 473 // // MessageBox.Show(musicPlayer.settings.volume.ToString()); 474 //} 475 //int t1 = 1; 476 //音量减 477 //private void btn_YL_jian_Click(object sender, EventArgs e) 478 //{ 479 // musicPlayer.settings.volume -= 5; 480 //} 481 //快进 482 //private void btn_kj_Click(object sender, EventArgs e) 483 //{ 484 // if (t1 == 1) 485 // { 486 // musicPlayer.Ctlcontrols.fastForward(); 487 // t1 = 2; 488 // } 489 // else 490 // { 491 // musicPlayer.Ctlcontrols.play(); 492 // t1 = 1; 493 // } 494 //} 495 //int t2 = 1; 496 //快退 497 //private void btn_kt_Click(object sender, EventArgs e) 498 //{ 499 // if (t2 == 1) 500 // { 501 // musicPlayer.Ctlcontrols.fastReverse(); 502 // t2 = 2; 503 // } 504 // else 505 // { 506 // musicPlayer.Ctlcontrols.play(); 507 // t2 = 1; 508 // } 509 //} 510 #endregion 511 512 #region 计时器timer3--关于播放模式(单曲循环) 513 private void timer3_Tick(object sender, EventArgs e) 514 { 515 if (musicPlayer.playState == WMPLib.WMPPlayState.wmppsPlaying) 516 { 517 double d1 = double.Parse(musicPlayer.currentMedia.duration.ToString()); 518 double d2 = double.Parse(musicPlayer.Ctlcontrols.currentPosition.ToString()) + 1; 519 if (d1 <= d2) 520 { 521 //得到当前选中项的索引 522 int index = lst_Playerfile.SelectedIndex; 523 524 //清空全部选中项的索引 525 lst_Playerfile.SelectedIndices.Clear(); 526 527 //将改变后的索引从新的赋值给当前选中项的索引 528 if (index != index_dq) 529 { 530 lst_Playerfile.SelectedIndex = index;//这里我写成index是由于 人性化些,歌曲是在单曲的可是你能够把索引放在别的文件上,不用让索引跳来挑去的 531 532 } 533 else 534 { 535 lst_Playerfile.SelectedIndex = index_dq; 536 } 537 musicPlayer.URL = listpath[index_dq]; 538 musicPlayer.Ctlcontrols.play(); 539 IsExistLrc(listpath[index_dq]); 540 } 541 } 542 } 543 #endregion 544 545 #region 计时器timer4--关于播放模式(随机播放) 546 private void timer4_Tick(object sender, EventArgs e) 547 { 548 int i_lst = lst_Playerfile.Items.Count - 1; 549 Random ran = new Random(); 550 int index_t4 = lst_Playerfile.SelectedIndex; 551 552 if (musicPlayer.playState == WMPLib.WMPPlayState.wmppsPlaying) 553 { 554 int vpc = ran.Next(0, i_lst); 555 double d1 = double.Parse(musicPlayer.currentMedia.duration.ToString()); 556 double d2 = double.Parse(musicPlayer.Ctlcontrols.currentPosition.ToString()) + 1; 557 if (d1 <= d2) 558 { 559 //得到当前选中项的索引 560 int index = vpc; 561 //清空全部选中项的索引 562 lst_Playerfile.SelectedIndices.Clear(); 563 //将索引赋值给当前选中项的索引 564 //if (index_t4 != index_dq) 565 //{ 566 lst_Playerfile.SelectedIndex = index;//这里我写成index是由于 人性化些,歌曲是在单曲的可是你能够把索引放在别的文件上,不用让索引跳来挑去的 567 index_dq = index; 568 //} 569 570 musicPlayer.URL = listpath[index]; 571 musicPlayer.Ctlcontrols.play(); 572 IsExistLrc(listpath[index]); 573 } 574 } 575 } 576 #endregion 577 578 #region 滚动播放进度条 579 private void trackBar1_Scroll(object sender, EventArgs e) 580 { 581 musicPlayer.Ctlcontrols.currentPosition = trackBar1.Value; 582 } 583 #endregion 584 585 bool loob = true; 586 587 #region 播放模式(单曲循环、顺序播放、随机播放、列表循环) 588 string strMucisMode = ""; 589 private void ClearCheck() 590 { 591 单曲循环ToolStripMenuItem1.Checked = false; 592 顺序播放ToolStripMenuItem1.Checked = false; 593 随机播放ToolStripMenuItem1.Checked = false; 594 列表循环ToolStripMenuItem1.Checked = false; 595 } 596 597 //播放模式的按钮 598 private void btn_PlayMode_Click(object sender, EventArgs e) 599 { 600 Point p = new Point(20, 0); 601 this.contextMenuStrip2.Show(btn_PlayMode, p);//定义相对于按钮的位置 602 } 603 int index_dq = 0; 604 private void 单曲循环ToolStripMenuItem1_Click(object sender, EventArgs e) 605 { 606 loob = false; 607 strMucisMode = "单曲循环"; 608 ClearCheck(); 609 单曲循环ToolStripMenuItem1.Checked = true; 610 btn_PlayMode.Image = Image.FromFile(".//image/danqu.png"); 611 toolTip1.SetToolTip(this.btn_PlayMode, "单曲循环");//当鼠标放在控件上会显示 612 613 timer4.Enabled = false; 614 timer3.Enabled = true; 615 } 616 private void 顺序播放ToolStripMenuItem1_Click(object sender, EventArgs e) 617 { 618 loob = true; 619 strMucisMode = "顺序播放"; 620 ClearCheck(); 621 顺序播放ToolStripMenuItem1.Checked = true; 622 btn_PlayMode.Image = Image.FromFile(".//image/shunxu.png"); 623 toolTip1.SetToolTip(this.btn_PlayMode, "顺序播放"); 624 625 timer3.Enabled = false; 626 timer4.Enabled = false; 627 } 628 private void 随机播放ToolStripMenuItem1_Click(object sender, EventArgs e) 629 { 630 loob = false; 631 strMucisMode = "随机播放"; 632 ClearCheck(); 633 随机播放ToolStripMenuItem1.Checked = true; 634 btn_PlayMode.Image = Image.FromFile(".//image/suiji.png"); 635 toolTip1.SetToolTip(this.btn_PlayMode, "随机播放"); 636 637 btn_Player.Text = "暂停"; 638 timer3.Enabled = false; 639 timer4.Enabled = true; 640 } 641 642 //列表循环和顺序播放是同样的 我就写成同样的了 643 private void 列表循环ToolStripMenuItem1_Click(object sender, EventArgs e) 644 { 645 loob = true; 646 strMucisMode = "列表循环"; 647 ClearCheck(); 648 列表循环ToolStripMenuItem1.Checked = true; 649 btn_PlayMode.Image = Image.FromFile(".//image/xunhuan.png"); 650 toolTip1.SetToolTip(this.btn_PlayMode, "列表循环"); 651 652 timer3.Enabled = false; 653 timer4.Enabled = false; 654 } 655 #endregion 656 657 #endregion 658 659 #region 四、桌面效果(桌面歌词、最小化) 660 661 #region 新建窗口Form2 显示桌面歌词 662 Form2 frm2 = Form2.GetSingle(); 663 /// <summary> 664 /// 显示桌面歌词 665 /// </summary> 666 /// <param name="sender"></param> 667 /// <param name="e"></param> 668 private void btn_Show_Click(object sender, EventArgs e) 669 { 670 if (btn_Show.Tag.ToString() == "show") 671 { 672 btn_Show.Tag = "hide"; 673 toolTip1.SetToolTip(this.btn_Show, "关闭桌面歌词"); 674 toolTip1.SetToolTip(this.Lb_show, "关闭桌面歌词"); 675 frm2.Show(); 676 } 677 else 678 { 679 btn_Show.Tag = "show"; 680 toolTip1.SetToolTip(this.btn_Show, "显示桌面歌词"); 681 toolTip1.SetToolTip(this.Lb_show, "显示桌面歌词"); 682 frm2.Hide();//隐藏窗口 此处不能关闭,若是关闭后 因为form2窗体是单例模式建立的 一次只能建立一个 关闭后将没法打开 683 } 684 } 685 #endregion 686 687 #region 最小化窗体 电脑右下角显示最小化图标 688 /// <summary> 689 /// 点击最小化按钮 690 /// </summary> 691 /// <param name="sender"></param> 692 /// <param name="e"></param> 693 private void btnMin_Click(object sender, EventArgs e) 694 { 695 if (this.WindowState != FormWindowState.Minimized) 696 { 697 this.Hide();//隐藏窗口 698 this.notifyIcon1.Visible = true;//右下角最小化图标可见 699 this.notifyIcon1.ShowBalloonTip(1000); //提示球 显示时间长度 700 } 701 } 702 /// <summary> 703 /// 双击电脑右下角程序图标 704 /// </summary> 705 /// <param name="sender"></param> 706 /// <param name="e"></param> 707 private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e) 708 { 709 this.Show();//显示窗体 710 } 711 //关闭窗口 712 private void btnExit_Click(object sender, EventArgs e) 713 { 714 this.Close(); 715 } 716 #endregion 717 718 #endregion 719 } 720 } 721 722 #region 网上对axWindowsMediaPlayer1的 概述 723 //利用axWindowsMediaPlayer(Windows Media Player)制做MP3播放器 2 724 //在制做mp3播放器以前,咱们须要了解axWindowsMediaPlayer 媒体主要方法属性: 725 //属性/方法名: 说明: 726 //[基本属性] 727 //URL:String; 指定媒体位置,本机或网络地址 728 //uiMode:String; 播放器界面模式,可为Full, Mini, None, Invisible 729 //playState:integer; 播放状态,1=中止,2=暂停,3=播放,6=正在缓冲,9=正在链接,10=准备就绪 730 //enableContextMenu:Boolean; 启用/禁用右键菜单 731 //fullScreen:boolean; 是否全屏显示 732 ////播放器基本控制 733 //Ctlcontrols.play; 播放 734 //Ctlcontrols.pause; 暂停 735 //Ctlcontrols.stop; 中止 736 //Ctlcontrols.currentPosition:double; 当前进度 737 //Ctlcontrols.currentPositionString:string; 当前进度,字符串格式。如“00:23” 738 //Ctlcontrols.fastForward; 快进 739 //Ctlcontrols.fastReverse; 快退 740 //Ctlcontrols.next; 下一曲 741 //Ctlcontrols.previous; 上一曲 742 //[settings] wmp.settings //播放器基本设置 743 //settings.volume:integer; 音量,0-100 744 //settings.autoStart:Boolean; 是否自动播放 745 //settings.mute:Boolean; 是否静音 746 //settings.playCount:integer; 播放次数 747 //[currentMedia] wmp.currentMedia //当前媒体属性 748 //currentMedia.duration:double; 媒体总长度 749 //currentMedia.durationString:string; 媒体总长度,字符串格式。如“03:24” 750 //currentMedia.getItemInfo(const string); 获取当前媒体信息"Title"=媒体标题,"Author"=艺术家,"Copyright"=版权信息,"Description"=媒体内容描述, "Duration"=持续时间(秒),"FileSize"=文件大小,"FileType"=文件类型,"sourceURL"=原始地址 751 //currentMedia.setItemInfo(const string); 经过属性名设置媒体信息 752 //currentMedia.name:string; 同 currentMedia.getItemInfo("Title") 753 //[currentPlaylist] wmp.currentPlaylist //当前播放列表属性 754 //currentPlaylist.count:integer; 当前播放列表所包含媒体数 755 //currentPlaylist.Item[integer]; 获取或设置指定项目媒体信息,其子属性同wmp.currentMedia 756 //axWindowsMediaPlayer1.currentMedia.sourceURL; //获取正在播放的媒体文件的路径 757 //axWindowsMediaPlayer1.currentMedia.name; //获取正在播放的媒体文件的名称 758 //axWindowsMediaPlayer1.Ctlcontrols.Play 播放 759 //axWindowsMediaPlayer1.Ctlcontrols.Stop 中止 760 //axWindowsMediaPlayer1.Ctlcontrols.Pause 暂停 761 //axWindowsMediaPlayer1.Ctlcontrols.PlayCount 文件播放次数 762 //axWindowsMediaPlayer1.Ctlcontrols.AutoRewind 是否循环播放 763 //axWindowsMediaPlayer1.Ctlcontrols.Balance 声道 764 //axWindowsMediaPlayer1.Ctlcontrols.Volume 音量 765 //axWindowsMediaPlayer1.Ctlcontrols.Mute 静音 766 //axWindowsMediaPlayer1.Ctlcontrols.EnableContextMenu 是否容许在控件上点击鼠标右键时弹出快捷菜单 767 //axWindowsMediaPlayer1.Ctlcontrols.AnimationAtStart 是否在播放前先播放动画 768 //axWindowsMediaPlayer1.Ctlcontrols.ShowControls 是否显示控件工具栏 769 //axWindowsMediaPlayer1.Ctlcontrols.ShowAudioControls 是否显示声音控制按钮 770 //axWindowsMediaPlayer1.Ctlcontrols.ShowDisplay 是否显示数据文件的相关信息 771 //axWindowsMediaPlayer1.Ctlcontrols.ShowGotoBar 是否显示Goto栏 772 //axWindowsMediaPlayer1.Ctlcontrols.ShowPositionControls 是否显示位置调节按钮 773 //axWindowsMediaPlayer1.Ctlcontrols.ShowStatusBar 是否显示状态栏 774 //axWindowsMediaPlayer1.Ctlcontrols.ShowTracker 是否显示进度条 775 //axWindowsMediaPlayer1.Ctlcontrols.FastForward 快进 776 //axWindowsMediaPlayer1.Ctlcontrols.FastReverse 快退 777 //axWindowsMediaPlayer1.Ctlcontrols.Rate 快进/快退速率 778 //axWindowsMediaPlayer1.AllowChangeDisplaySize 是否容许自由设置播放图象大小 779 //axWindowsMediaPlayer1.DisplaySize 设置播放图象大小 780 // 1-MpDefaultSize 原始大小 781 // 2-MpHalfSize 原始大小的一半 782 // 3-MpDoubleSize 原始大小的两倍 783 // 4-MpFullScreen 全屏 784 // 5-MpOneSixteenthScreen 屏幕大小的1/16 785 // 6-MpOneFourthScreen 屏幕大小的1/4 786 // 7-MpOneHalfScreen 屏幕大小的1/2 787 //axWindowsMediaPlayer1.ClickToPlay 是否容许单击播放窗口启动Media Player 788 //在视频播放以后,能够经过以下方式读取源视频的宽度和高度,而后设置其还原为原始的大小. 789 // private void ResizeOriginal() 790 // { 791 // int intWidth = axWindowsMediaPlayer1.currentMedia.imageSourceWidth; 792 // int intHeight = axWindowsMediaPlayer1.currentMedia.imageSourceHeight; 793 // axWindowsMediaPlayer1.Width = intWidth + 2; 794 // axWindowsMediaPlayer1.Height = intHeight + 2; 795 // } 796 //打开媒体文件并播放: 797 // Dim filePath As String 798 // With Me.OpenFileDialog1 799 // .Title = "打开语音文件" 800 // .CheckPathExists = True 801 // .CheckFileExists = True 802 // .Multiselect = False 803 // .Filter = "mp3文件(*.mp3)|*.mp3|全部文件(*.*)|*.*" 804 // If .ShowDialog = DialogResult.Cancel Then 805 // Exit Sub 806 // End If 807 // filePath = .FileName 808 // End With 809 // Me.Text = "PC复读机-文件 " & filePath 810 // AxWindowsMediaPlayer1.URL = filePath 811 // Try 812 // Me.AxWindowsMediaPlayer1.Ctlcontrols.play() 813 // Catch ex As Exception 814 // MsgBox("对不起,不能播放此格式语音文件", MsgBoxStyle.OKOnly, "PC复读机") 815 // Exit Sub 816 // End Try 817 //注意: 818 //AxWindowsMediaPlayer1.URL 中URL是表示要播放的文件名,取消了原来的Name属性. 819 //AxWindowsMediaPlayer1.Ctlcontrols.play()播放,一样还有Pause,Stop等其余属性. 820 //AxWindowsMediaPlayer1.settings.balance表示媒体播放的声道设置,0表示均衡,-1和1表示左右声道. 821 //AxWindowsMediaPlayer1.currentMedia.duration 表示要播放的文件的时间长度.可用它获取文件长度. 822 //AxWindowsMediaPlayer1.Ctlcontrols.currentPosition表示正在播放的文件的当前播放位置,可用这个属性来对媒体文件进行前进后退等设置.如 823 //AxWindowsMediaPlayer1.Ctlcontrols.currentPosition+1 表示前进1个时间单位. 824 //AxWindowsMediaPlayer1.settings.rate播放速率,通常乘以16后再显示kbps单位. 825 //注意:在上面程序中,若是在后面加上一个: 826 //msgbox(AxWindowsMediaPlayer1.currentMedia.duration.ToString ) 827 //则显示结果极可能为0,所以,这时候极可能获取不到文件的播放时间长度,容易出错。因此在利用的时候能够加一个timer控件: 828 //Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick 829 // EndPoint = AxWindowsMediaPlayer1.currentMedia.duration 830 // If EndPoint = 0 Then Exit Sub '可能由于媒体文件的打开须要必定时间,这里等待媒体文件的打开 831 // msgbox(AxWindowsMediaPlayer1.currentMedia.duration.ToString ) 832 //End Sub 833 //此时msgbox便会显示文件播放长度。 834 //2. Ctlcontrols属性 835 //Ctlcontrols属性是AxWindowsMediaPlayer的一个重要属性, 此控件中有许多经常使用成员。 836 //(1) 方法play 837 //用于播放多媒体文件,其格式为: 838 //窗体名.控件名.Ctlcontrols.play() 839 //如: AxWindowsMediaPlayer1.Ctlcontrols.play() ‘此处缺省窗体名是Me 840 //(2) 方法pause 841 //用于暂停正在播放的多媒体文件,其格式为: 842 //窗体名.控件名.Ctlcontrols.pause() 843 //如: AxWindowsMediaPlayer1.Ctlcontrols.pause() 844 //(3) 方法stop 845 //用于中止正在播放的多媒体文件,其格式为: 846 //窗体名.控件名.Ctlcontrols.stop() 847 //如: AxWindowsMediaPlayer1.Ctlcontrols.stop() 848 //(4) 方法fastforward 849 //用于将正在播放的多媒体文件快进,其格式为: 850 //窗体名.控件名.Ctlcontrols.fastforward() 851 //如: AxWindowsMediaPlayer1.Ctlcontrols.forward() 852 //(5) 方法fastreverse 853 //窗体名.控件名.Ctlcontrols.fastreverse() 854 //如: AxWindowsMediaPlayer1.Ctlcontrols.fastreverse() 855 //6. 属性CurrentPosition 856 //用于获取多媒体文件当前的播放进度,其值是数值类型,使用格式为: 857 //窗体名.控件名.Ctlcontrols.currentPosition 858 //d1 =AxWindowsMediaPlayer1.Ctlcontrols.currentPosition 859 //其中d1 是一个整型变量。 860 //7. 属性Duration 861 //用于获取当前多媒体文件的播放的总时间,其值为数值类型,其使用格式为: 862 //窗体名.控件名.currentMedia.duration 863 //如:d2 =AxWindowsMediaPlayer1.currentMedia.duration 864 //其中d2是一个整型变量。 865 #endregion

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 10 namespace 音乐播放器 11 { 12 public partial class Form2 : Form 13 { 14 public Form2() 15 { 16 InitializeComponent(); 17 } 18 19 #region 一、单例模式(只显示一个窗体) 20 public static string strMusicLrc = " "; 21 22 public static Form2 FrmSingle = null;//建立一个单例模式 23 24 //提供一个静态方法 若是窗体未被建立则返回一个新窗体 25 public static Form2 GetSingle() 26 { 27 if (FrmSingle == null) 28 { 29 FrmSingle = new Form2(); 30 } 31 return FrmSingle; 32 } 33 #endregion 34 35 #region 二、设置From2 的起始位置 36 private void Form2_Load(object sender, EventArgs e) 37 { 38 this.Location = new Point(200, 600);//设置窗口出现的位置 39 40 //如下两行代码能够将窗体设置为透明背景 41 this.BackColor = Color.Black; 42 this.TransparencyKey = this.BackColor; 43 } 44 #endregion 45 46 #region 三、建立一个静态方法 经过静态方法进行歌词传递 47 private static string _strLrc; 48 public static string StrLrc 49 { 50 get { return _strLrc; } 51 set { _strLrc = value; } 52 } 53 54 //定时刷新歌词 55 private void timer1_Tick(object sender, EventArgs e) 56 { 57 label1.Text = StrLrc; 58 } 59 #endregion 60 61 #region 窗体移动 62 bool formMoveFlag = false;//窗体是否移动标志位位 63 Point formPoint;//记录窗体的位置 64 /// <summary> 65 /// 鼠标在窗体上按下 66 /// </summary> 67 /// <param name="sender"></param> 68 /// <param name="e"></param> 69 private void MainForm_MouseDown(object sender, MouseEventArgs e) 70 { 71 formPoint = new Point(); 72 73 if (e.Button == MouseButtons.Left)//若是鼠标左键按下 74 { 75 formPoint = new Point(-e.X, -e.Y); //获得变量的值 76 formMoveFlag = true;//开始移动 77 78 #region 还有种方法 79 // int x; 80 // int y; 81 //x = -e.X - SystemInformation.FrameBorderSize.Width;//获取当前X坐标 82 //y = -e.Y - SystemInformation.CaptionHeight - SystemInformation.FrameBorderSize.Height;//获取当前Y坐标 83 //formPoint = new Point(x, y); 84 //formMove = true;//开始移动 85 #endregion 86 } 87 } 88 /// <summary> 89 /// 鼠标在窗体上移动 90 /// </summary> 91 /// <param name="sender"></param> 92 /// <param name="e"></param> 93 private void MainForm_MouseMove(object sender, MouseEventArgs e) 94 { 95 if (formMoveFlag == true)//若是窗体正在移动 96 { 97 Point mousePos = Control.MousePosition;//获取鼠标当前位置 98 mousePos.Offset(formPoint.X, formPoint.Y);//设置鼠标移动后的位置 99 Location = mousePos;//将鼠标的坐标 传递给窗体 100 } 101 } 102 /// <summary> 103 /// 鼠标在窗体上释放 104 /// </summary> 105 /// <param name="sender"></param> 106 /// <param name="e"></param> 107 private void MainForm_MouseUp(object sender, MouseEventArgs e) 108 { 109 if (e.Button == MouseButtons.Left)//按下的是鼠标左键 110 { 111 formMoveFlag = false;//中止移动 112 } 113 } 114 #endregion 115 } 116 }
播放mp3的实体图:
播放mv的实体图:
2、线程
1.建立线程_前台_后台_挂起_唤醒_阻塞_终止_优先级

1 using System;
2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 7 namespace 建立线程_前台_后台_挂起_唤醒_阻塞_终止_优先级 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 //建立线程 14 Thread t1 = new Thread(new ThreadStart(TestMethod)); 15 Thread t2 = new Thread(new ParameterizedThreadStart(TestMethod)); 16 Thread t3 = new Thread(new ThreadStart(TestMethod)); 17 Thread t4 = new Thread(new ThreadStart(s5000)); 18 19 //我把他们的排序从高到低----优先级 20 //Highest 在具备任何其余优先级的线程以前 21 //AboveNormal 能够将Thread安排在具备highest优先级线程以后,在Normal以前 22 //Normal 在AboveNormal以后,BelowNormal以前。默认值。 23 //BelowNormal 在Normal以后,Lowest以前 24 //Lowest 在具备其余任何优先级的线程以后 25 26 //Priority属性来获取和设置其优先级 27 t1.Priority = ThreadPriority.Highest; 28 //t2.Priority = ThreadPriority.AboveNormal; 29 //t3.Priority = ThreadPriority.AboveNormal;//能够不用写,这是默认的 30 //t4.Priority = ThreadPriority.AboveNormal; 31 32 #region 线程的前台、后台的区别 33 //建立线程默认是前台的 34 //当全部前台线程关闭时,全部的后台线程也会被直接终止,不会抛出异常。 35 //当程序主线程被关闭时前台线程是不会关闭的,当前台线程所有结束后,整个程序结束 36 t1.IsBackground = true;//手动将前台线程改为后台线程IsBackground 37 t2.IsBackground = true; 38 //这时,t3,t4仍是前台线程 39 #endregion 40 41 #region t1线程被挂起,唤醒。t2线程正常启动 42 //!我学习这段时发现 挂起和唤醒已通过时了 不用怕,下面还有各类各样的线程锁 43 t1.Start(); 44 t1.Suspend();//线程t1被挂起 -->Suspend 45 t2.Start("hello"); 46 Thread.Sleep(1000);//使主线程休眠1s 47 Console.ReadKey(); 48 //在随便点击按钮后,线程t1被唤醒,恢复线程 -->Resume 49 t1.Resume(); 50 #endregion 51 52 #region 对中断、停止、终止的理解 53 //中断 :计算机执行某程序时,发生了紧急事件或有特殊请求,中央处理机暂停某程序的执行,而去处理上述事件或请求,处理完毕后再从新执行某程序的过程。 54 //停止 :中途中止。 55 //终止 :结束;中止。 56 #endregion 57 58 #region Abort和Join的搭配使用 59 //线程被终止,就中止运行,是没法恢复的,由于 Windows 会永久地删除被停止线程的全部数据。 60 //1.abort()的功能是用来终止调用此方法的线程的,只是在多数状况下, 61 //它须要一点时间,有些延迟(可能在短期内此线程还在执行)... 62 //2.join()方法它的功能不是终止线程,而是在t线程终止以前,阻止正在结束 63 //(调用了abort()方法但还未结束)的t线程执行,同时使主线程等待, 64 //直到t线程终止(也就是abort()方法终止过程完毕)了再执行下面的代码, 65 //打印出来的结果,执行状态就为FALSE,线程状态也为中止了 66 t3.Start(); 67 t3.Abort(); //终止线程 使用Abort()方法 68 //t3.Start();//线程正在运行或被终止;它没法从新启动。 这样是错误的 69 Console.WriteLine("线程t3被终止,按任意键继续"); 70 t3.Join();//等待线程t3终止结束以后才能继续向下进行 71 Console.ReadKey(); 72 #endregion 73 74 //join和sleep的区别 75 t4.Start(); 76 Console.WriteLine("开始默念五个数"); 77 t4.Join(); //阻塞 等待线程t4执行结束在执行下面的代码 78 t4.Join(5000);//他俩同样都是阻塞,这个只是阻塞5秒钟,无论t4线程有没有结束5s以后就继续向下执行,不要误解 在5s内t4线程结束了就会当即向下执行 这就是join和sleep的区别 79 80 Console.WriteLine(t1.Name + "状态:" + t1.ThreadState + " " + t1.IsAlive); 81 Console.WriteLine(t2.Name + "状态:" + t2.ThreadState + " " + t2.IsAlive); 82 Console.WriteLine(t3.Name + "状态:" + t3.ThreadState + " " + t3.IsAlive); 83 Console.WriteLine(t4.Name + "状态:" + t4.ThreadState + " " + t4.IsAlive); 84 Console.ReadKey(); 85 } 86 87 public static void TestMethod() 88 { 89 Console.WriteLine("不带参数的线程"); 90 } 91 92 public static void TestMethod(object data) 93 { 94 string datastr = data as string; 95 Console.WriteLine("带参数的线程函数,参数为:{0}", datastr); 96 } 97 98 public static void s5000() 99 { 100 Thread.Sleep(5000);//线程停留5秒 101 } 102 } 103 }
2.同步

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 7 #region 同步和异步的区别 8 ////同步、异步和并行的讲解:(百度上找的) 9 ////假如5个菜分别是A,B,C,D,E 你有两个炉子 只能同时炒A跟B 10 ////因此剩下的CDE只能等AB炒完了才能开始 这个等待就是同步 咱们叫作阻塞 即这个时候你只能作AB这两个菜 11 12 ////假如你还有一台咖啡机, 你在炒AB的时候 把咖啡豆跟水放到咖啡机里打开开关 你就能够不用去管它了 13 ////咱们说 咱们新开了一个线程煮咖啡 可是注咖啡这个动做不妨碍你炒菜 因此煮咖啡这个线程是异步的 咱们叫非阻塞 14 15 ////等到咖啡机 叮--- 告诉你咖啡煮好了 这个时候你去把咖啡拿出来 叮的这一声 咱们叫通知 通知主线程也就是你 16 ////我(咖啡机)的工做作完了, 你去把咖啡拿出来 咱们叫回调 也就是 咖啡机线程完成以后 通知主线程要作的动做 17 18 ////简单来说 会占用你的时间 让你没法作其它事情的任务 叫同步任务(炒菜要专一 否则可能会糊锅)。 19 ////那些不须要占用你的时间的任务 叫异步任务 咖啡机本身会把咖啡煮好 不须要你一直看着它 20 21 ////只有两个炉子,那就只能有2我的炒, 这个叫并行 22 #endregion 23 #region 注意这里ManualResetEvent和AutoResetEvent的一个重要区别: 24 // manual的话确定会给线程1和线程2都发送一个信号,而auto只会随机给其中一个发送信号。 25 26 //为何一个叫manual而一个叫auto呢?我想这是不少人的疑问,如今咱们就来看这个问题。 27 // 刚才_manualResetEvent .Set();的这句话我想你们都明白了,能够看作将IsRelease的属性设置为true.线程1中 28 // _manualResetEvent.WaitOne();接收到信号后再也不阻塞线程1。在此以后的整个过程当中IsRelease的值都是true.若是 29 //想将IsRelease的值回复成false,就必须再调用_manualResetEvent.Reset()的方法。 30 31 // 若是是_autoResetEvent.set(),那么_autoResetEvent.WaitOne()后会自动将IsRelease的值自动设置为false. 32 //这就是为何一个叫auto,一个叫manual. 33 #endregion 34 35 namespace 简单的同步 36 { 37 class Program 38 { 39 static AutoResetEvent myResetEvent = new AutoResetEvent(false);//默认阻塞当前线程 40 static AutoResetEvent ChangeEvent = new AutoResetEvent(false); 41 //static ManualResetEvent myResetEvent = new ManualResetEvent(false);//默认阻塞当前线程 42 //static ManualResetEvent ChangeEvent = new ManualResetEvent(false); 43 static int number; //这是关键资源 44 45 static void Main() 46 { 47 Thread payMoneyThread = new Thread(new ThreadStart(PayMoneyProc)); 48 //Thread payMoneyThread = new Thread(PayMoneyProc);//也能够写成这样 49 payMoneyThread.Name = "付钱线程"; 50 51 Thread getBookThread = new Thread(new ThreadStart(GetBookProc)); 52 getBookThread.Name = "取书线程"; 53 54 payMoneyThread.IsBackground = true; 55 getBookThread.IsBackground = true; 56 57 payMoneyThread.Start(); 58 getBookThread.Start(); 59 60 for (int i = 1; i <= 10; i++) 61 { 62 Console.WriteLine("买书线程:数量{0}", i);//这个主线程运行的 63 number = i; 64 myResetEvent.Set();//发送信号 65 //ChangeEvent.Set(); 66 Thread.Sleep(1000); 67 } 68 payMoneyThread.Abort(); 69 getBookThread.Abort(); 70 Console.ReadKey(); 71 } 72 73 static void PayMoneyProc() 74 { 75 while (true) 76 { 77 myResetEvent.WaitOne();//接收信号 78 //myResetEvent.Reset(); 79 Console.WriteLine("{0}:数量{1}", Thread.CurrentThread.Name, number); 80 ChangeEvent.Set(); 81 } 82 } 83 static void GetBookProc() 84 { 85 while (true) 86 { 87 ChangeEvent.WaitOne(); 88 //ChangeEvent.Reset(); 89 Console.WriteLine("{0}:数量{1}", Thread.CurrentThread.Name, number); 90 Console.WriteLine("------------------------------------------"); 91 //Thread.Sleep(0); 92 } 93 } 94 } 95 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 7 //当要求使用volatile 声明的变量的值的时候,系统老是从新从它所在的内存读取数据, 8 //即便它前面的指令刚刚从该处读取过数据。并且读取的数据马上被保存。 9 10 //调用GetAge()获得的是“主”内存区域的Age数值。 11 //用volatile修饰后的变量不容许有不一样于“主”内存区域的变量拷贝。 12 //换句话说,一个变量经volatile修饰后在全部线程中必须是同步的; 13 //任何线程中改变了它的值,全部其余线程当即获取到了相同的值。 14 //理所固然的,volatile修饰的变量存取时比通常变量消耗的资源要多一点; 15 //所以线程有它本身的变量拷贝更为高效。 16 namespace volatile_同步 17 { 18 class Program 19 { 20 static volatile int Age = 10;//其实不加volatile输出也同样,有点抽象,内存内的值 21 22 public static int GetAge1() 23 { 24 Age = 20; 25 return Age; 26 } 27 28 public static int GetAge2() 29 { 30 Age = 30; 31 return Age; 32 } 33 34 public static void Age1() 35 { 36 for (int i = 0; i < 10; i++) 37 { 38 Thread.Sleep(1000); 39 Console.WriteLine("Age1=" + Age); 40 } 41 } 42 43 static void Main(string[] args) 44 { 45 Thread t1 = new Thread(Age1); 46 t1.IsBackground = true; 47 t1.Start(); 48 Thread.Sleep(3000); 49 GetAge1(); 50 Thread.Sleep(3000);//先运行一会GetAge1,在运行GetAge2 51 GetAge2();//运行GetAge2时观察Age1值变没?变了就是同步。 52 53 Console.Read(); 54 } 55 } 56 } 57 #region volatile的详解和与lock的不一样 58 //volatile多用于多线程的环境,当一个变量定义为volatile时, 59 //读取这个变量的值时候每次都是从momery里面读取而不是从cache读。 60 //这样作是为了保证读取该变量的信息都是最新的,而不管其余线程如何更新这个变量。 61 62 // 更通俗的解释: 63 //Volatile 字面的意思时易变的,不稳定的。在C#中也差很少能够这样理解。 64 //编译器在优化代码时,可能会把常常用到的代码存在Cache里面,而后下一次调用就直接读取Cache而不是内存,这样就大大提升了效率。可是问题也随之而来了。 65 //在多线程程序中,若是把一个变量放入Cache后,又有其余线程改变了变量的值,那么本线程是没法知道这个变化的。它可能会直接读Cache里的数据。可是很不幸,Cache里的数据已通过期了,读出来的是不合时宜的脏数据。这时就会出现bug。 66 //用Volatile声明变量能够解决这个问题。用Volatile声明的变量就至关于告诉编译器,我不要把这个变量写Cache,由于这个变量是可能发生改变的。 67 68 //volatile解决问题1:CPU缓存 69 //volatile解决问题2:编译器优化(指令乱序) 70 71 //volatile 关键字表示字段可能被多个并发执行线程修改。声明为 volatile 的字段不受编译器优化(假定由单个线程访问)的限制。这样能够确保该字段在任什么时候间呈现的都是最新的值。 72 //volatile 修饰符一般用于由多个线程访问而不使用 lock 语句(C# 参考) 语句对访问进行序列化的字段。有关在多线程方案中使用 volatile 的示例,请参见如何:建立和终止线程(C# 编程指南)。 73 //volatile 关键字可应用于如下类型的字段: 74 //引用类型。 75 //指针类型(在不安全的上下文中)。请注意,虽然指针自己能够是可变的,可是它指向的对象不能是可变的。换句话说,您没法声明“指向可变对象的指针”。 76 //整型,如 sbyte、byte、short、ushort、int、uint、char、float 和 bool。 77 //具备整数基类型的枚举类型。 78 //已知为引用类型的泛型类型参数。 79 //IntPtr 和 UIntPtr。 80 81 //volatile是最简单的一种同步方法,固然简单是要付出代价的。它只能在变量一级作同步, 82 //volatile的含义就是告诉处理器, 不要将我放入工做内存, 请直接在主存操做我。 83 //所以,当多线程同时访问该变量时,都将直接操做主存,从本质上作到了变量共享。 84 85 86 //颇有道理::: 87 //C# volatile 与 lock 88 //volatile的使用场景:多个线程同时访问一个变量,CLR为了效率,容许每一个线程进行本地缓存, 89 //这就致使了变量的不一致性。volatile就是为了解决这个问题,volatile修饰的变量, 90 //不容许线程进行本地缓存,每一个线程的读写都是直接操做在共享内存上, 91 //这就保证了变量始终具备一致性。缺点很明显:牺牲了效率。 92 93 //lock的使用场景:多个线程同时访问一个代码块,使用lock 修饰该代码块,强制多个线程进行排队, 94 //一个接一个的去访问。缺点很明显:排队进行必然致使效率低。 95 96 //系统中应该尽可能减小lock的使用(也就是排队执行的状况),由于根据阿姆达尔定律: 97 //S=1/(a+(1-a)/n) ,其中S 为加速比,a 为串行计算部分,n为并行计算节点,该公式意味着: 98 //若是具有足够的并行计算节点,要想增长系统的速度,必须减小串行部分。由于串行意味着, 99 //一我的作的时候,其余人必须等着。Google 的MapReduce,也就是把串行计算转化为并行计算。 100 #endregion

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 7 //在这篇博客里学习的 http://www.cnblogs.com/zhycyq/articles/2679017.html 8 namespace _3._1Monitor_Wait___Pulse___PulseAll__ 9 { 10 class Program 11 { 12 static void Main(string[] args) 13 { 14 //开启三个线程 15 new Thread(A).Start(); 16 new Thread(B).Start(); 17 new Thread(C).Start(); 18 Console.ReadLine(); 19 } 20 21 //1.必需要先知道:object这是 .NET Framework 中全部类的最终基类 22 //2.lock(object对象) 就是把.NET Framework 中全部类都加上锁了 23 //三个进程中A没有睡眠直接进入就绪队列,B、C在外面(等待队列中),此时A是lockObj的拥有者 24 //而后结果1s后A用Pulus发出信号,容许第一个等待队列中的线程B进入就绪队列,线程B也是用Pulus发出信号,使线程C进入了就绪队列。 25 //线程A用Wait放弃同步对象,进入了等待队列 26 //此时就绪队列中线程B是lockObj的拥有者开始执行了 27 //线程B结束后线程C拥有了lockObj使用权,开始执行 28 //线程C结束了,同步对象闲置,A就从新获得了同步对象 29 //线程A开始执行了 30 31 //最后提醒一下,线程是没有前后顺序的,A先进入就绪队列得到拥有权这是必定的 32 //接下来B和C不清楚是谁先进来的了,还有最后A和剩下的那个线程谁先获得拥有权也是未知的 33 //上面的 解释方法思考 34 35 static object lockObj = new object(); 36 static void A() 37 { 38 lock (lockObj) //线程A直接进入就绪队列 39 { 40 Thread.Sleep(1000); 41 Monitor.Pulse(lockObj); 42 Monitor.Wait(lockObj); //自我流放到等待队列 43 } 44 Console.WriteLine("A exit..."); 45 } 46 static void B() 47 { 48 Thread.Sleep(500); 49 lock (lockObj) //线程B500ms后进入就绪队列 50 { 51 Monitor.Pulse(lockObj); 52 } 53 Console.WriteLine("B exit..."); 54 } 55 static void C() 56 { 57 Thread.Sleep(800); 58 lock (lockObj) //线程C800ms后进入就绪队列 59 { } 60 Console.WriteLine("C exit..."); 61 } 62 } 63 64 //下面的这个 和上面的这个思路差很少,就不解释了,用的是线程池 65 //class MyManualEvent 66 //{ 67 // private object lockObj = new object(); 68 // private bool hasSet = false; 69 // public void Set() 70 // { 71 // lock (lockObj) 72 // { 73 // hasSet = true; 74 // Monitor.PulseAll(lockObj); 75 // } 76 // } 77 // public void WaitOne() 78 // { 79 // lock (lockObj) 80 // { 81 // while (!hasSet) 82 // { 83 // Monitor.Wait(lockObj); 84 // } 85 // } 86 // } 87 //} 88 //class Program 89 //{ 90 // static MyManualEvent myManualEvent = new MyManualEvent(); 91 // static void Main(string[] args) 92 // { 93 // ThreadPool.QueueUserWorkItem(WorkerThread, "A"); 94 // ThreadPool.QueueUserWorkItem(WorkerThread, "B"); 95 // Console.WriteLine("Press enter to signal the green light"); 96 // Console.ReadLine(); 97 // myManualEvent.Set(); 98 // ThreadPool.QueueUserWorkItem(WorkerThread, "C"); 99 // Console.ReadLine(); 100 // } 101 // static void WorkerThread(object state) 102 // { 103 // myManualEvent.WaitOne(); 104 // Console.WriteLine("Thread {0} got the green light...", state); 105 // } 106 //} 107 }

1 using System; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System.Threading; 5 6 //Monitor类提供了与lock相似的功能,不过与lock不一样的是,它能更好的控制同步块, 7 //当调用了Monitor的Enter(Object o)方法时,会获取o的独占权,直到调用Exit(Object o)方法时, 8 //才会释放对o的独占权,能够屡次调用Enter(Object o)方法,只须要调用一样次数的Exit(Object o)方法 9 //便可,Monitor类同时提供了TryEnter(Object o,[int])的一个重载方法,该方法尝试获取o对象的独占权, 10 //当获取独占权失败时,将返回false。 11 12 // 但使用 lock 一般比直接使用 Monitor 更可取,一方面是由于 lock 更简洁, 13 //另外一方面是由于 lock 确保了即便受保护的代码引起异常,也能够释放基础监视器。 14 //这是经过 finally 中调用Exit来实现的。事实上,lock 就是用 Monitor 类来实现的。 15 //下面两段代码是等效的: 16 17 //1.Monitor.Enter(object)方法是获取锁,Monitor.Exit(object)方法是释放锁,这就是Monitor最经常使用的两个方法,固然在使用过程当中为了不获取锁以后由于异常,致锁没法释放,因此须要在try{} catch(){}以后的finally{}结构体中释放锁(Monitor.Exit())。 18 //2.Monitor的经常使用属性和方法: 19 // Enter(Object) 在指定对象上获取排他锁。 20 // Exit(Object) 释放指定对象上的排他锁。 21 // IsEntered 肯定当前线程是否保留指定对象锁。 22 // Pulse 通知等待队列中的线程锁定对象状态的更改。 23 // PulseAll 通知全部的等待线程对象状态的更改。 24 // TryEnter(Object) 试图获取指定对象的排他锁。 25 // TryEnter(Object, Boolean) 尝试获取指定对象上的排他锁,并自动设置一个值,指示是否获得了该锁。 26 // Wait(Object) 释放对象上的锁并阻止当前线程,直到它从新获取该锁。 27 28 //两个线程之间如何协同工做。 29 //这个程序的思路是共同作一件事情(从一个ArrayList中删除元素),若是执行完成了,两个线程都中止执行。 30 31 public class ThreadDemo 32 { 33 private Thread threadOne; 34 private Thread threadTwo; 35 private ArrayList stringList; 36 private event EventHandler OnNumberClear;//数据删除完成引起的事件 37 public static void Main() 38 { 39 ThreadDemo demo = new ThreadDemo(1000); 40 demo.Action(); 41 Console.WriteLine(); 42 Thread.Sleep(10000); 43 Console.ReadKey(); 44 } 45 public ThreadDemo(int number) 46 { 47 Random random = new Random(1000000); 48 stringList = new ArrayList(number); 49 for (int i = 0; i < number; i++) 50 { 51 stringList.Add(random.Next().ToString()); 52 } 53 threadOne = new Thread(new ThreadStart(Run));//两个线程共同作一件事情 54 threadTwo = new Thread(new ThreadStart(Run));//两个线程共同作一件事情 55 threadOne.Name = "线程1"; 56 threadTwo.Name = "线程2"; 57 OnNumberClear += new EventHandler(ThreadDemo_OnNumberClear); 58 } 59 /// <summary> 60 /// 开始工做 61 /// </summary> 62 public void Action() 63 { 64 threadOne.Start(); 65 threadTwo.Start(); 66 } 67 /// <summary> 68 /// 共同作的工做 69 /// </summary> 70 private void Run() 71 { 72 string stringValue = null; 73 while (true) 74 { 75 Monitor.Enter(this);//锁定,保持同步 76 stringValue = (string)stringList[0]; 77 Console.WriteLine(Thread.CurrentThread.Name + "删除了" + stringValue); 78 stringList.RemoveAt(0);//删除ArrayList中的元素 79 if (stringList.Count == 0) 80 { 81 OnNumberClear(this, new EventArgs());//引起完成事件 82 } 83 Monitor.Exit(this);//取消锁定 84 Thread.Sleep(5); 85 } 86 } 87 88 //执行完成以后,中止全部线程 89 void ThreadDemo_OnNumberClear(object sender, EventArgs e) 90 { 91 Console.WriteLine("执行完了,中止了全部线程的执行。"); 92 threadTwo.Abort(); 93 threadOne.Abort(); 94 } 95 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 7 #region 一看就能懂 lock使用范围 8 //lock: 9 //class A 10 // { 11 // } 12 //struct S 13 //{ 14 //} 15 //int i; 16 //object o; 17 //string str; 18 //A a=new A(); 19 //S s=new S(); 20 //lock(i){}//错误 21 //lock(o){}//正确 22 //lock(str){}//正确 23 //lock(a){}//正确 24 //lock(s){}//错误 25 #endregion 26 27 #region 重点: 28 //lock的参数必须是基于引用类型的对象,不要是基本类型像bool,int什么的, 29 //这样根本不能同步,缘由是lock的参数要求是对象,若是传入int, 30 //势必要发生装箱操做,这样每次lock的都将是一个新的不一样的对象。 31 //最好避免使用public类型或不受程序控制的对象实例,由于这样极可能致使死锁。 32 //特别是不要使用字符串做为lock的参数,由于字符串被CLR“暂留”, 33 //就是说整个应用程序中给定的字符串都只有一个实例,所以更容易形成死锁现象。 34 //建议使用不被“暂留”的私有或受保护成员做为参数。其实某些类已经提供了专门用于被锁的成员, 35 //好比Array类型提供SyncRoot,许多其它集合类型也都提供了SyncRoot。 36 // 因此,使用lock应该注意如下几点: 37 38 // 1、若是一个类的实例是public的,最好不要lock(this)。 39 //由于使用你的类的人也许不知道你用了lock,若是他new了一个实例, 40 //而且对这个实例上锁,就很容易形成死锁。 41 42 // 2、若是MyType是public的,不要lock(typeof(MyType)) 43 44 // 3、永远也不要lock一个字符串 45 #endregion 46 //说明: 47 // private static object ojb = new object(); 48 // lock(obj) 49 // { 50 // //锁定运行的代码段 51 // } 52 //假设线程A先执行,线程B稍微慢一点。线程A执行到lock语句,判断obj是否已申请了互斥锁, 53 //判断依据是逐个与已存在的锁进行object.ReferenceEquals比较(此处未加证明),若是不存在, 54 //则申请一个新的互斥锁,这时线程A进入lock里面了。 55 //这时假设线程B启动了,而线程A还未执行完lock里面的代码。线程B执行到lock语句, 56 //检查到obj已经申请了互斥锁,因而等待;直到线程A执行完毕,释放互斥锁, 57 //线程B才能申请新的互斥锁并执行lock里面的代码。 58 namespace _4.lock同步互斥锁 59 { 60 //为了能看的清楚一些,我是将两个线程分别执行两个方法,这两个方法调用同一个方法 61 //测试lock能不能使一个进程执行时另外一个线程等待,这时不肯定两个线程哪一个先启动的,没肯定优先级 62 63 #region 不加lock的输出 64 //我是线程t2 65 //我是线程t1 66 //我是线程t1 67 //我是线程t2 68 //我是线程t2 69 //我是线程t1 70 //我是线程t1 71 //我是线程t2 72 //我是线程t2 73 //我是线程t1 74 //不加lock 输出的没有顺序,加入操做大文件更改或其余操做时很容易死锁 75 #endregion 76 77 #region 加lock的输出 78 //我是线程t2 79 //我是线程t2 80 //我是线程t2 81 //我是线程t2 82 //我是线程t2 83 //我是线程t1 84 //我是线程t1 85 //我是线程t1 86 //我是线程t1 87 //我是线程t1 88 //加锁后多线程同步时不会产生死锁,一个线程执行时另外一个线程在等待 89 //别误会为何是线程t2先执行的,能够想象好多人在跑步比赛,这是随机的 90 #endregion 91 92 partial class Class1//我没有 写成public 93 { 94 //Class1 c1 = new Class1();//要用public 就实例化 使用lock(c1) 95 public void T1(object tt1) 96 { 97 Count(tt1); 98 } 99 public void T2(object tt2) 100 { 101 Count(tt2); 102 } 103 public void Count(object str) 104 { 105 lock (this)//不加锁直接把这段去掉 106 for (int i = 0; i < 5; i++) 107 { 108 Thread.Sleep(500); 109 Console.WriteLine(str as string); 110 } 111 } 112 } 113 class Program 114 { 115 static void Main(string[] args) 116 { 117 Class1 c1 = new Class1(); 118 Thread t1 = new Thread(c1.T1); 119 Thread t2 = new Thread(c1.T2); 120 121 t1.IsBackground = true; 122 t2.IsBackground = true; 123 124 string str1 = "我是线程t1"; 125 string str2 = "我是线程t2"; 126 127 t1.Start(str1); 128 t2.Start(str2); 129 130 while (true) 131 { 132 if (t1.IsAlive == true || t2.IsAlive == true) 133 { 134 //使主线程停顿一下,只是方便理解,不加这段也是同样的, 135 //两个线程没执行完毕时主线程已经停在循环内了 136 Thread.Sleep(1000); 137 } 138 else 139 break; 140 } 141 Console.WriteLine("回车,结束"); 142 Console.Read(); 143 } 144 } 145 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 //对于整数数据类型的简单操做,能够用 Interlocked 类的成员来实现线程同步, 6 //存在于System.Threading命名空间。Interlocked类有如下方法:Increment , 7 //Decrement , Exchange 和CompareExchange 。使用Increment 和Decrement 8 //能够保证对一个整数的加减为一个原子操做。Exchange 方法自动交换指定变量的值。 9 //CompareExchange 方法组合了两个操做:比较两个值以及根据比较的结果将第三个值 10 //存储在其中一个变量中。比较和交换操做也是按原子操做执行的。 11 namespace _5.Interlocked整数数据类型同步 12 { 13 class Program 14 { 15 static void Main(string[] args) 16 { 17 int i = 2; 18 System.Threading.Interlocked.Increment(ref i);//递增i--> 2+1 = 3 19 Console.WriteLine(i); 20 System.Threading.Interlocked.Decrement(ref i);//递减i--> 3-1 = 2 21 Console.WriteLine(i); 22 System.Threading.Interlocked.Exchange(ref i, 100);//指定的值返回i=100 23 Console.WriteLine(i); 24 System.Threading.Interlocked.CompareExchange(ref i, 10, 100);//若是10和100是个相等的数就返回相同的那个数,不等就返回第一个数 25 Console.WriteLine(i); 26 27 Console.Read(); 28 } 29 } 30 }

1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using System.Threading; 5 6 //下面是ReaderWriterLock类中的四个主要方法: 7 // a. AcquireReaderLock(): 这个重载方法获取一个读者锁,接受一个整型或者TimeSpan类型的timeout 值。timeout是一个检测死锁的利器。 8 // b. AcquireWriterLock(): 这个重载方法获取一个写者锁,接受一个整型或者TimeSpan类型的timeout 值。 9 // c. ReleaseReaderLock(): 释放读者锁。 10 // d. ReleaseWriterLock(): 释放写者锁。 11 12 //线程wt1 和 wt2 是WriteInts()方法中得到写锁的写者线程,线程rt1 和 rt2 是在ReadInts()方法中 13 //得到读者锁的读者线程。在WriteInts()方法中,变量x 和 y 的值分别被改为a 和 b. 当线程wt1 或 14 //wt2 经过调用AcquireWriterLock() 方法得到一个写者锁后,那么直到这个线程经过调用 15 //ReleaseWriterLock()方法释放锁以前任何其余线程(包括读者线程rt1 和 rt2)都不被容许访问相应对象。 16 //这个行为与Monitors相似 。在ReadInts()方法中,线程rt1 和 rt2 经过调用AcquireReaderLock()方法 17 //得到读者锁, 这两个线程能够并发地访问变量x 和 y. 直到读者线程释放它们的读者锁之后,写者线程 18 //(wt1 和 wt2)才被容许访问对应对象。只有读者线程在得到读者锁之后才能够并发地访问。 19 20 //Monitors类对于只想来读数据而非写数据来讲过于“安全”了。Monitors 也有一些性能问题, 21 //对于只读类型的访问来讲,性能瓶颈是能够避免的。ReaderWriterLock类经过容许任意数量的线程 22 //并发地读取数据来提供一个解决数据读-写问题的完美方案。当线程更新数据时锁住数据。当没有 23 //写者线程拥有锁的时候写者线程能够得到锁。写者锁能够在没有读者线程或者写者线程拥有锁的时候 24 //得到锁。所以,ReaderWriterLock 就像是一段关键部分代码, 它也支持一个timeout 值,而这方面 25 //在检测死锁时很是有用。 26 namespace ReadWriteLock 27 { 28 public class ReadWrite 29 { 30 private ReaderWriterLock rwl; 31 private int x; 32 private int y; 33 34 public ReadWrite() 35 { 36 rwl = new ReaderWriterLock(); 37 } 38 39 public void ReadInts(ref int a, ref int b) 40 { 41 rwl.AcquireReaderLock(Timeout.Infinite); 42 try 43 { 44 a = this.x; 45 b = this.y; 46 } 47 finally 48 { 49 rwl.ReleaseReaderLock(); 50 } 51 } 52 53 public void WriteInts(int a, int b) 54 { 55 rwl.AcquireWriterLock(Timeout.Infinite); 56 try 57 { 58 this.x = a; 59 this.y = b; 60 Console.WriteLine("x = " + this.x 61 + " y = " + this.y 62 + " ThreadID = " + Thread.CurrentThread.GetHashCode()); 63 } 64 finally 65 { 66 rwl.ReleaseWriterLock(); 67 } 68 } 69 } 70 71 public class RWApp 72 { 73 private ReadWrite rw = new ReadWrite(); 74 75 public static void Main(string[] args) 76 { 77 RWApp e = new RWApp(); 78 79 Thread wt1 = new Thread(new ThreadStart(e.Write)); 80 wt1.Start(); 81 Thread wt2 = new Thread(new ThreadStart(e.Write)); 82 wt2.Start(); 83 84 Thread rt1 = new Thread(new ThreadStart(e.Read)); 85 rt1.Start(); 86 Thread rt2 = new Thread(new ThreadStart(e.Read)); 87 rt2.Start(); 88 89 Console.ReadLine(); 90 } 91 92 private void Write() 93 { 94 int a = 10; 95 int b = 11; 96 Console.WriteLine("************** Write *************"); 97 98 for (int i = 0; i < 5; i++) 99 { 100 this.rw.WriteInts(a++, b++); 101 Thread.Sleep(1000); 102 } 103 } 104 105 private void Read() 106 { 107 int a = 10; 108 int b = 11; 109 Console.WriteLine("************** Read *************"); 110 111 for (int i = 0; i < 5; i++) 112 { 113 this.rw.ReadInts(ref a, ref b); 114 Console.WriteLine("For i = " + i 115 + " a = " + a 116 + " b = " + b 117 + " TheadID = " + Thread.CurrentThread.GetHashCode()); 118 Thread.Sleep(1000); 119 } 120 } 121 } 122 } 123 #region 拥有独占权的 写的时候 读要等待 124 //在考虑资源访问的时候,惯性上咱们会对资源实施lock机制,可是在某些状况下, 125 //咱们仅仅须要读取资源的数据,而不是修改资源的数据,在这种状况下获取资源的 126 //独占权无疑会影响运行效率,所以.Net提供了一种机制,使用ReaderWriterLock进行 127 //资源访问时,若是在某一时刻资源并无获取写的独占权,那么能够得到多个读的访问权, 128 //单个写入的独占权,若是某一时刻已经获取了写入的独占权,那么其它读取的访问权必须进行等待, 129 130 //private static ReaderWriterLock m_readerWriterLock = new ReaderWriterLock(); 131 //private static int m_int = 0; 132 //[STAThread] 133 //static void Main(string[] args) 134 //{ 135 //Thread readThread = new Thread(new ThreadStart(Read)); 136 //readThread.Name = "ReadThread1"; 137 //Thread readThread2 = new Thread(new ThreadStart(Read)); 138 //readThread2.Name = "ReadThread2"; 139 //Thread writeThread = new Thread(new ThreadStart(Writer)); 140 //writeThread.Name = "WriterThread"; 141 //readThread.Start(); 142 //readThread2.Start(); 143 //writeThread.Start(); 144 //readThread.Join(); 145 //readThread2.Join(); 146 //writeThread.Join(); 147 148 //Console.ReadLine(); 149 //} 150 //private static void Read() 151 //{ 152 //while (true) 153 //{ 154 //Console.WriteLine("ThreadName " + Thread.CurrentThread.Name + " AcquireReaderLock"); 155 //m_readerWriterLock.AcquireReaderLock(10000); 156 //Console.WriteLine(String.Format("ThreadName : {0} m_int : {1}", Thread.CurrentThread.Name, m_int)); 157 //m_readerWriterLock.ReleaseReaderLock(); 158 //} 159 //} 160 161 //private static void Writer() 162 //{ 163 //while (true) 164 //{ 165 //Console.WriteLine("ThreadName " + Thread.CurrentThread.Name + " AcquireWriterLock"); 166 //m_readerWriterLock.AcquireWriterLock(1000); 167 //Interlocked.Increment(ref m_int); 168 //Thread.Sleep(5000); 169 //m_readerWriterLock.ReleaseWriterLock(); 170 //Console.WriteLine("ThreadName " + Thread.CurrentThread.Name + " ReleaseWriterLock"); 171 //} 172 //} 173 174 //能够看到,当WriterThread获取到写入独占权后,任何其它读取的线程都必须等待, 175 //直到WriterThread释放掉写入独占权后,才能获取到数据的访问权,应该注意的是, 176 //上述打印信息很明显显示出,能够多个线程同时获取数据的读取权, 177 //这从ReadThread1和ReadThread2的信息交互输出能够看出。 178 #endregion

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Runtime.Remoting.Contexts; 6 using System.Threading; 7 8 #region 详解 9 //SynchronizationAttribute 10 // 当咱们肯定某个类的实例在同一时刻只能被一个线程访问时,咱们能够直接将类标识成Synchronization的,这样,CLR会自动对这个类实施同步机制,实际上,这里面涉及到同步域的概念,当类按以下设计时,咱们能够确保类的实例没法被多个线程同时访问 11 // 1). 在类的声明中,添加System.Runtime.Remoting.Contexts.SynchronizationAttribute属性。 12 // 2). 继承至System.ContextBoundObject 13 // 须要注意的是,要实现上述机制,类必须继承至System.ContextBoundObject,换句话说,类必须是上下文绑定的。 14 // 一个示范类代码以下: 15 //[System.Runtime.Remoting.Contexts.Synchronization] 16 //public class SynchronizedClass : System.ContextBoundObject 17 //{ 18 19 //} 20 #endregion 21 22 //SynchronizationAttribute对于缺少同步经验的程序员来讲,使用起来很方便。 23 24 namespace _9.SynchronizationAttribute多线程同步代码区 25 { 26 class Program 27 { 28 static void Main(string[] args) 29 { 30 Sy c1 = new Sy(); 31 Thread t1 = new Thread(c1.T1); 32 Thread t2 = new Thread(c1.T2); 33 34 t1.IsBackground = true; 35 t2.IsBackground = true; 36 37 string str1 = "我是线程t1"; 38 string str2 = "我是线程t2"; 39 40 t1.Start(str1); 41 t2.Start(str2); 42 43 while (true) 44 { 45 if (t1.IsAlive == true || t2.IsAlive == true) 46 { 47 //使主线程停顿一下,只是方便理解,不加这段也是同样的, 48 //两个线程没执行完毕时主线程已经停在循环内了 49 Thread.Sleep(1000); 50 } 51 else 52 break; 53 } 54 Console.WriteLine("回车,结束"); 55 Console.Read(); 56 } 57 } 58 [Synchronization] 59 public class Sy : ContextBoundObject //上下文绑定 60 { 61 public void T1(object tt1) 62 { 63 Count(tt1); 64 } 65 public void T2(object tt2) 66 { 67 Count(tt2); 68 } 69 public void Count(object str) 70 { 71 //lock (this) 72 //我以前写过的lock锁,不加lock两个线程会同时执行这个方法,很容易会死锁 73 //我这方法内容少,大内容就容易死锁了。 74 //这样对比就很明显了,不加lock线程也实现了同步,一个线程执行时另个一个线程等待 75 //这就是SynchronizationAttribute它的好处 76 for (int i = 0; i < 5; i++) 77 { 78 Thread.Sleep(500); 79 Console.WriteLine(str as string); 80 } 81 } 82 } 83 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace _7._2Mutex验证两个进程内的线程同时访问同一个资源 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 #region 只能运行一个客户端程序 13 bool flag = false; 14 System.Threading.Mutex mutex = new System.Threading.Mutex(true, "Test", out flag); 15 //第一个参数:true--给调用线程赋予互斥体的初始所属权 16 //第一个参数:互斥体的名称 17 //第三个参数:返回值,若是调用线程已被授予互斥体的初始所属权,则返回true 18 if (!flag) 19 { 20 Console.WriteLine("只能运行一个客户端程序!"); 21 Console.Read(); 22 Environment.Exit(1);//退出程序 23 } 24 #endregion 25 26 Console.Read(); 27 } 28 } 29 } 30 31 //------------------------------------------------------------- 32 using System; 33 using System.Collections.Generic; 34 using System.Linq; 35 using System.Text; 36 using System.Threading; 37 38 //C#语言有不少值得学习的地方,这里咱们主要介绍C# Mutex对象,包括介绍控制好多个线程相互之间的联系等方面。 39 //如何控制好多个线程相互之间的联系,不产生冲突和重复,这须要用到互斥对象,即:System.Threading 命名空间中的 Mutex 类。 40 //咱们能够把Mutex看做一个出租车,乘客看做线程。乘客首先等车,而后上车,最后下车。当一个乘客在车上时,其余乘客就只有 41 //等他下车之后才能够上车。而线程与C# Mutex对象的关系也正是如此,线程使用Mutex.WaitOne()方法等待C# Mutex对象被释放, 42 //若是它等待的C# Mutex对象被释放了,它就自动拥有这个对象,直到它调用Mutex.ReleaseMutex()方法释放这个对象,而在此期间, 43 //其余想要获取这个C# Mutex对象的线程都只有等待。 44 //下面这个例子使用了C# Mutex对象来同步四个线程,主线程等待四个线程的结束,而这四个线程的运行又是与两个C# Mutex对象相关联的。 45 //其中还用到AutoResetEvent类的对象,能够把它理解为一个信号灯。这里用它的有信号状态来表示一个线程的结束。 46 47 #region 这个有些复杂 先不研究 48 namespace ThreadExample 49 { 50 public class MutexSample 51 { 52 static Mutex gM1; 53 static Mutex gM2; 54 const int ITERS = 100; 55 static AutoResetEvent Event1 = new AutoResetEvent(false); 56 static AutoResetEvent Event2 = new AutoResetEvent(false); 57 static AutoResetEvent Event3 = new AutoResetEvent(false); 58 static AutoResetEvent Event4 = new AutoResetEvent(false); 59 60 public static void Main(String[] args) 61 { 62 Console.WriteLine("Mutex Sample "); 63 //建立一个Mutex对象,而且命名为MyMutex 64 gM1 = new Mutex(true, "MyMutex"); 65 //建立一个未命名的Mutex 对象. 66 gM2 = new Mutex(true); 67 Console.WriteLine(" - Main Owns gM1 and gM2"); 68 69 AutoResetEvent[] evs = new AutoResetEvent[4]; 70 evs[0] = Event1; //为后面的线程t1,t2,t3,t4定义AutoResetEvent对象 71 evs[1] = Event2; 72 evs[2] = Event3; 73 evs[3] = Event4; 74 75 MutexSample tm = new MutexSample(); 76 Thread t1 = new Thread(new ThreadStart(tm.t1Start)); 77 Thread t2 = new Thread(new ThreadStart(tm.t2Start)); 78 Thread t3 = new Thread(new ThreadStart(tm.t3Start)); 79 Thread t4 = new Thread(new ThreadStart(tm.t4Start)); 80 t1.Start();// 使用Mutex.WaitAll()方法等待一个Mutex数组中的对象所有被释放 81 t2.Start();// 使用Mutex.WaitOne()方法等待gM1的释放 82 t3.Start();// 使用Mutex.WaitAny()方法等待一个Mutex数组中任意一个对象被释放 83 t4.Start();// 使用Mutex.WaitOne()方法等待gM2的释放 84 85 Thread.Sleep(2000); 86 Console.WriteLine(" - Main releases gM1"); 87 gM1.ReleaseMutex(); //线程t2,t3结束条件知足 88 89 Thread.Sleep(1000); 90 Console.WriteLine(" - Main releases gM2"); 91 gM2.ReleaseMutex(); //线程t1,t4结束条件知足 92 93 //等待全部四个线程结束 94 WaitHandle.WaitAll(evs); 95 Console.WriteLine(" Mutex Sample"); 96 Console.ReadLine(); 97 } 98 99 public void t1Start() 100 { 101 Console.WriteLine("t1Start started, Mutex.WaitAll(Mutex[])"); 102 Mutex[] gMs = new Mutex[2]; 103 gMs[0] = gM1;//建立一个Mutex数组做为Mutex.WaitAll()方法的参数 104 gMs[1] = gM2; 105 Mutex.WaitAll(gMs);//等待gM1和gM2都被释放 106 Thread.Sleep(2000); 107 Console.WriteLine("t1Start finished, Mutex.WaitAll(Mutex[]) satisfied"); 108 Event1.Set(); //线程结束,将Event1设置为有信号状态 109 } 110 public void t2Start() 111 { 112 Console.WriteLine("t2Start started, gM1.WaitOne( )"); 113 gM1.WaitOne();//等待gM1的释放 114 Console.WriteLine("t2Start finished, gM1.WaitOne( ) satisfied"); 115 Event2.Set();//线程结束,将Event2设置为有信号状态 116 } 117 public void t3Start() 118 { 119 Console.WriteLine("t3Start started, Mutex.WaitAny(Mutex[])"); 120 Mutex[] gMs = new Mutex[2]; 121 gMs[0] = gM1;//建立一个Mutex数组做为Mutex.WaitAny()方法的参数 122 gMs[1] = gM2; 123 Mutex.WaitAny(gMs);//等待数组中任意一个Mutex对象被释放 124 Console.WriteLine("t3Start finished, Mutex.WaitAny(Mutex[])"); 125 Event3.Set();//线程结束,将Event3设置为有信号状态 126 } 127 public void t4Start() 128 { 129 Console.WriteLine("t4Start started, gM2.WaitOne( )"); 130 gM2.WaitOne();//等待gM2被释放 131 Console.WriteLine("t4Start finished, gM2.WaitOne( )"); 132 Event4.Set();//线程结束,将Event4设置为有信号状态 133 } 134 } 135 } 136 #endregion

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 using System.Runtime.CompilerServices; 7 8 #region 讲解 9 //MethodImplAttribute 10 //若是临界区是跨越整个方法的,也就是说,整个方法内部的代码都须要上锁的话, 11 //使用MethodImplAttribute属性会更简单一些。这样就不用在方法内部加锁了, 12 //只须要在方法上面加上 [MethodImpl(MethodImplOptions.Synchronized)] 就能够了, 13 //MehthodImpl和MethodImplOptions都在命名空间System.Runtime.CompilerServices 里面。 14 //但要注意这个属性会使整个方法加锁,直到方法返回,才释放锁。所以,使用上不太灵活。 15 //若是要提早释放锁,则应该使用Monitor或lock。 16 #endregion 17 18 //我这人比较懒,我仍是用lock那个试验来讲明如何给方法加锁的 19 namespace _10.MethodImplAttribute给方法加锁 20 { 21 partial class Class1//我没有 写成public 22 { 23 //Class1 c1 = new Class1();//要用public 就实例化 使用lock(c1) 24 public void T1(object tt1) 25 { 26 Count(tt1); 27 } 28 public void T2(object tt2) 29 { 30 Count(tt2); 31 } 32 33 //首先先肯定了,要被多个线程访问的共同方法。就是他 34 //而后在该方法头上写上[MethodImpl(MethodImplOptions.Synchronized)] 35 //这样就能够去掉lock锁了,结果是同样的 36 [MethodImpl(MethodImplOptions.Synchronized)] 37 public void Count(object str) 38 { 39 //lock (this) 40 for (int i = 0; i < 5; i++) 41 { 42 Thread.Sleep(500);//能够不写。为了看效果用的 43 Console.WriteLine(str as string); 44 } 45 } 46 } 47 48 class Program 49 { 50 static void Main(string[] args) 51 { 52 Class1 c1 = new Class1(); 53 Thread t1 = new Thread(c1.T1); 54 Thread t2 = new Thread(c1.T2); 55 56 t1.IsBackground = true; 57 t2.IsBackground = true; 58 59 string str1 = "我是线程t1"; 60 string str2 = "我是线程t2"; 61 62 t1.Start(str1); 63 t2.Start(str2); 64 65 while (true) 66 { 67 if (t1.IsAlive == true || t2.IsAlive == true) 68 { 69 //使主线程停顿一下,只是方便理解,不加这段也是同样的, 70 //两个线程没执行完毕时主线程已经停在循环内了 71 Thread.Sleep(1000); 72 } 73 else 74 break; 75 } 76 Console.WriteLine("回车,结束"); 77 Console.Read(); 78 } 79 } 80 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 //用lock和Monitor能够很好地起到线程同步的做用,但它们没法实现线程之间传递事件。 7 //若是要实现线程同步的同时,线程之间还要有交互,就要用到同步事件。 8 //同步事件是有两个状态(终止和非终止)的对象,它能够用来激活和挂起线程。 9 10 //AutoResetEvent自动变为非终止,就是说一个AutoResetEvent只能激活一个线程。 11 namespace _12.同步事件AutoResetEvent_线程之间传递事件_ 12 { 13 class Program 14 { 15 const int numIterations = 5; 16 17 static AutoResetEvent myResetEvent = new AutoResetEvent(false); 18 static int number; 19 static void Main() 20 { 21 Thread myReaderThread1 = new Thread(new ThreadStart(MyReadThreadProc1)); 22 Thread myReaderThread2 = new Thread(new ThreadStart(MyReadThreadProc2)); 23 myReaderThread1.Name = "ReaderThread1"; 24 myReaderThread2.Name = "ReaderThread2"; 25 myReaderThread1.Start(); 26 myReaderThread2.Start(); 27 for (int i = 1; i <= numIterations; i++) 28 { 29 Console.WriteLine("Writer thread writing value: {0}", i); 30 number = i; 31 // 发信号,说明值已经被写进去了。这里的意思是说Set是一个发信号的方法。 32 myResetEvent.Set(); 33 myResetEvent.Set(); 34 //怕会误会“是否是就发了一个信号,才一个线程接到的”,我这发两个信号,结果在下面 35 #region 这我就很少解释了,仔细想一想就明白了,两个信号不必定是哪一个线程接受到了(包括重复接收) 36 //Writer thread writing value: 1 37 //ReaderThread2 reading value: 1 38 //Writer thread writing value: 2 39 //ReaderThread2 reading value: 2 40 //ReaderThread1 reading value: 2 41 //Writer thread writing value: 3 42 //ReaderThread2 reading value: 3 43 //Writer thread writing value: 4 44 //ReaderThread2 reading value: 4 45 //ReaderThread1 reading value: 4 46 //Writer thread writing value: 5 47 //ReaderThread2 reading value: 5 48 #endregion 49 //事实证实AutoResetEvent的特性,不能够写成多发信号,只有一对一 50 51 Thread.Sleep(1000); 52 } 53 myReaderThread1.Abort(); 54 myReaderThread2.Abort(); 55 56 Console.Read(); 57 58 #region 结果是不固定的 我收集了一份,一看便知道AutoResetEvent它的特色了 59 //它发送的信号,只有一个能接收到,不会启动多个线程 60 61 //Writer thread writing value: 1 62 //ReaderThread1 reading value: 1 63 //Writer thread writing value: 2 64 //ReaderThread1 reading value: 2 65 //Writer thread writing value: 3 66 //ReaderThread2 reading value: 3 67 //Writer thread writing value: 4 68 //ReaderThread2 reading value: 4 69 //Writer thread writing value: 5 70 //ReaderThread1 reading value: 5 71 #endregion 72 } 73 static void MyReadThreadProc1() 74 { 75 while (true) 76 { 77 //在数据被做者写入以前不会被读者读取 78 myResetEvent.WaitOne();//接受到信号后,表明 写完能够看了 79 //还有一点就是:收到信号后会自动关闭信号 80 Console.WriteLine("{0} reading value: {1}", Thread.CurrentThread.Name, number); 81 //myResetEvent.Reset();//将其设置为无信号//已经无信号了,能够不用写 82 } 83 } 84 85 static void MyReadThreadProc2() 86 { 87 while (true) 88 { 89 //声明一下:AutoResetEvent里没有WaitAny和WaitAll方法 90 //在数据被做者写入以前不会被读者读取 91 myResetEvent.WaitOne();//接受到信号后,表明 写完能够看了 92 Console.WriteLine("{0} reading value: {1}", Thread.CurrentThread.Name, number); 93 } 94 } 95 } 96 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 7 //将AutoResetEvent里的代码改为下面这样子 8 namespace _12.同步事件ManualResetEvent__线程之间传递事件一对多_ 9 { 10 class Program 11 { 12 const int numIterations = 5; 13 14 static ManualResetEvent myManualResetEvent = new ManualResetEvent(false); 15 static int number; 16 static void Main() 17 { 18 Thread myReaderThread1 = new Thread(new ThreadStart(MyReadThreadProc1)); 19 Thread myReaderThread2 = new Thread(new ThreadStart(MyReadThreadProc2)); 20 myReaderThread1.Name = "ReaderThread1"; 21 myReaderThread2.Name = "ReaderThread2"; 22 myReaderThread1.Start(); 23 myReaderThread2.Start(); 24 for (int i = 1; i <= numIterations; i++) 25 { 26 Console.WriteLine("Writer thread writing value: {0}", i); 27 number = i; 28 // 发信号,说明值已经被写进去了。这里的意思是说Set是一个发信号的方法。 29 myManualResetEvent.Set();//发送信号,两个线程都会收到信号 30 31 Thread.Sleep(1000); 32 } 33 myReaderThread1.Abort(); 34 myReaderThread2.Abort(); 35 36 Console.Read(); 37 } 38 static void MyReadThreadProc1() 39 { 40 while (true) 41 { 42 //在数据被做者写入以前不会被读者读取 43 myManualResetEvent.WaitOne();//接受到信号后,表明 写完能够看了 44 Console.WriteLine("{0} reading value: {1}", Thread.CurrentThread.Name, number); 45 myManualResetEvent.Reset();//将其设置为无信号 46 } 47 } 48 49 static void MyReadThreadProc2() 50 { 51 while (true) 52 { 53 //在数据被做者写入以前不会被读者读取 54 myManualResetEvent.WaitOne();//接受到信号后,表明 写完能够看了 55 //还有一点就是:收到信号后会不自动关闭信号 56 Console.WriteLine("{0} reading value: {1}", Thread.CurrentThread.Name, number); 57 myManualResetEvent.Reset();//将其设置为无信号 58 } 59 } 60 } 61 }
3.线程池

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 7 //它有一些限制: 8 //1. 线程池中全部线程都是后台线程,若是进程的全部前台线程都结束了,全部的后台线程就会中止。不能把入池的线程改成前台线 程。 9 //2. 不能给入池的线程设置优先级或名称。 10 //3. 对于COM对象,入池的全部线程都是多线程单元(Multi-threaded apartment,MTA)线程。许多COM对象都须要单线程单元(Single -threaded apartment,STA)线程。 11 //4.入池的线程只能用于时间较短的任务。若是线程要一直运行(如Word的拼写检查器线程),就应使用Thread类建立一个线程。 12 //这是个简单的线程池操做,能够扩展利用多线程的同步,异步 13 //因为线程的建立和销毁须要耗费必定的开销,过多的使用线程会形成内存资源的浪费,出于对性能的考虑, 14 //因而引入了线程池的概念。线程池维护一个请求队列,线程池的代码从队列提取任务,而后委派给线程池 15 //的一个线程执行,线程执行完不会被当即销毁,这样既能够在后台执行任务,又能够减小线程建立和销毁 16 //所带来的开销。 17 18 //线程池线程默认为后台线程(IsBackground)。 19 namespace 线程池 20 { 21 class Program 22 { 23 static void Main(string[] args) 24 { 25 //将工做项加入到线程池队列中,这里能够传递一个线程参数 26 ThreadPool.QueueUserWorkItem(TestMethod, "Hello"); 27 Thread.Sleep(1000); 28 29 Console.ReadKey(); 30 } 31 32 public static void TestMethod(object data) 33 { 34 string datastr = data as string; 35 Console.WriteLine(datastr); 36 } 37 } 38 }
4.异步

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 7 namespace 异步1.线程池异步 8 { 9 class Program 10 { 11 public static void MyMethodA() 12 { 13 for (int i = 0; i < 3; i++) 14 { 15 Console.WriteLine("我是MyMethodA" + i); 16 } 17 } 18 public static void MyMethodB() 19 { 20 for (int i = 0; i < 3; i++) 21 { 22 Console.WriteLine("我是MyMethodB" + i); 23 } 24 } 25 26 static void Main(string[] args) 27 { 28 using (ManualResetEvent m1 = new ManualResetEvent(false)) 29 using (ManualResetEvent m2 = new ManualResetEvent(false)) 30 { 31 ThreadPool.QueueUserWorkItem(delegate 32 { 33 MyMethodA(); 34 m1.Set(); 35 }); 36 ThreadPool.QueueUserWorkItem(delegate 37 { 38 MyMethodB(); 39 m2.Set(); 40 }); 41 WaitHandle.WaitAll(new WaitHandle[] { m1, m2, }); 42 #region 看两次输出的结果,能够看出是异步进行的 43 //1. 44 //我是MyMethodA0 45 //我是MyMethodB0 46 //我是MyMethodB1 47 //我是MyMethodB2 48 //我是MyMethodA1 49 //我是MyMethodA2 50 //2. 51 //我是MyMethodA0 52 //我是MyMethodA1 53 //我是MyMethodB0 54 //我是MyMethodB1 55 //我是MyMethodB2 56 //我是MyMethodA2 57 #endregion 58 } 59 Console.Read(); 60 } 61 } 62 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Threading; 7 //Task 的优势以及功能 8 //一、在任务启动后,能够随时以任务延续的形式注册回调。 9 //二、经过使用 ContinueWhenAll 和 ContinueWhenAny 方法或者 WaitAll 方法或 WaitAny 方法,协调多个为了响应 Begin_ 方法而执行的操做。 10 //三、在同一Task 对象中封装异步 I/O 绑定和计算绑定操做。 11 //四、监视Task 对象的状态。 12 //五、使用TaskCompletionSource 将操做的状态封送到Task 对象。 13 namespace 异步2.Task_异步等待_wait_waitall_waitany 14 { 15 class Program 16 { 17 public static void MyMethodA() 18 { 19 for (int i = 0; i < 5; i++) 20 { 21 Console.WriteLine(DateTime.Now.ToString()); 22 Thread.Sleep(1000); 23 } 24 } 25 public static void MyMethodB() 26 { 27 for (int i = 0; i < 5; i++) 28 { 29 Console.WriteLine(DateTime.Now.ToString()); 30 Thread.Sleep(1000); 31 } 32 } 33 34 static void Main(string[] args) 35 { 36 Task t1 = new Task(MyMethodA);//也能够这么写都是同样的,前提要加上t1.Start()才能执行 37 Task t2 = Task.Factory.StartNew(delegate { MyMethodB(); }); 38 t1.Start(); 39 //它是一个一个的等待结束 40 //t1.Wait(); 41 //t2.Wait(); 42 43 //这是同时进行的异步.先把上面的两行注释掉 44 //等待对象完成执行过程 45 Task.WaitAll(t1, t2); 46 //Task.WaitAny(t1, t2);//等待一个线程结束 47 Console.WriteLine("主线程已结束"); 48 Console.Read(); 49 50 #region 不加Wait、WaitAll会怎样输出 51 //主线程已结束 52 //2016/12/8 9:52:34 53 //2016/12/8 9:52:34 54 //2016/12/8 9:52:35 55 //2016/12/8 9:52:35 56 //2016/12/8 9:52:36 57 //2016/12/8 9:52:36 58 //2016/12/8 9:52:37 59 //2016/12/8 9:52:37 60 //2016/12/8 9:52:38 61 //2016/12/8 9:52:38 62 63 //加上它仍是有好处的 64 #endregion 65 } 66 } 67 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 异步3.Task捕获异常 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 Task t1 = new Task(MyMethod); 14 t1.Start(); 15 t1.Wait(); 16 //发生一个或多个错误 17 //缘由我告诉你: 18 //Task的异常会从新抛到Wait和AllWait中 19 //捕获异常方法很简单还记得try catch吧,把t1.Wait()写成下面的这样就好了 20 //try { t1.Wait();} catch (Exception e) { Console.WriteLine(e); } 21 22 Console.WriteLine("主线程代码运行结束"); 23 Console.ReadLine(); 24 } 25 26 static void MyMethod() 27 { 28 throw new Exception("Task异常测试"); 29 //点击运行时会在这里报异常,由于这是本身设置的异常,不用管他,点击F5继续 30 //你会发现异常停在了t1.Wait()位置 31 } 32 } 33 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 异步4.Task返回值 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 Task<int> task = new Task<int>(() => 14 { 15 int sum = 0; 16 Console.WriteLine("使用Task执行异步操做."); 17 for (int i = 0; i < 100; i++) 18 { 19 sum += i; 20 } 21 return sum; 22 }); 23 //启动任务,并安排到当前任务队列线程中执行任务(System.Threading.Tasks.TaskScheduler) 24 task.Start(); 25 26 Console.WriteLine("主线程执行其余处理"); 27 //等待任务的完成执行过程。 28 task.Wait(); 29 //得到任务的执行结果 30 Console.WriteLine("任务执行结果:{0}", task.Result.ToString()); 31 32 Console.Read(); 33 } 34 } 35 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 using System.Threading.Tasks; 7 8 //使用CancellationTokenSource对象须要与Task对象进行配合使用,Task会对当前运行的状态进行控制 9 //(这个不用咱们关心是如何孔控制的)。而CancellationTokenSource则是外部对Task的控制, 10 //如取消、定时取消。 11 12 //Task.Factory.StartNew 建立并启动了 MyTask 方法,并传递了一个 CancellationTokenSource.Token 13 //对象进去。咱们能够经过在外部CancellationTokenSource对象进行控制是否取消任务的运行。 14 //当在 MyTask 中的 cancelTokenSource.IsCancellationRequested 判断若是是取消了任务的话 15 //就跳出while循环执行。也就结束了任务 16 namespace 异步5.CancellationTokenSource_终止线程 17 { 18 class Program 19 { 20 //声明CancellationTokenSource对象 21 static CancellationTokenSource cancelTokenSource = new CancellationTokenSource(); 22 23 //程序入口 24 static void Main(string[] args) 25 { 26 ; 27 Task.Factory.StartNew(MyTask, cancelTokenSource.Token); 28 29 Console.WriteLine("请按回车键(Enter)中止"); 30 Console.ReadLine(); 31 32 cancelTokenSource.Cancel(); 33 34 Console.WriteLine("已中止"); 35 Console.ReadLine(); 36 } 37 38 //测试方法 39 static void MyTask() 40 { 41 //判断是否取消任务 42 while (!cancelTokenSource.IsCancellationRequested) 43 { 44 Console.WriteLine(DateTime.Now); 45 Thread.Sleep(1000); 46 } 47 } 48 } 49 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 using System.Threading.Tasks; 7 8 namespace 异步5._2.CancellationTokenSource_终止多个线程 9 { 10 class Program 11 { 12 //声明CancellationTokenSource对象 13 static CancellationTokenSource c1 = new CancellationTokenSource(); 14 static CancellationTokenSource c2 = new CancellationTokenSource(); 15 static CancellationTokenSource c3 = new CancellationTokenSource(); 16 17 //使用多个CancellationTokenSource进行复合管理 18 static CancellationTokenSource compositeCancel = CancellationTokenSource.CreateLinkedTokenSource(c1.Token, c2.Token, c3.Token); 19 20 //程序入口 21 static void Main(string[] args) 22 { 23 //Task.Factory.StartNew(MyTask, compositeCancel.Token); 24 Task.Factory.StartNew(MyTask1, c1.Token); 25 Task.Factory.StartNew(MyTask2, c2.Token); 26 Task.Factory.StartNew(MyTask3, c3.Token); 27 28 Console.WriteLine("请按回车键(Enter)中止"); 29 Console.ReadLine(); 30 31 //任意一个 CancellationTokenSource 取消任务,那么全部任务都会被取消。 32 c1.Cancel(); 33 34 Console.WriteLine("已中止"); 35 Console.ReadLine(); 36 } 37 38 //测试方法 39 static void MyTask1() 40 { 41 //判断是否取消任务 42 while (!compositeCancel.IsCancellationRequested) 43 { 44 Console.WriteLine("C1"); 45 Thread.Sleep(1000); 46 } 47 } 48 static void MyTask2() 49 { 50 //判断是否取消任务 51 while (!compositeCancel.IsCancellationRequested) 52 { 53 Console.WriteLine("C2"); 54 Thread.Sleep(1000); 55 } 56 } 57 static void MyTask3() 58 { 59 //判断是否取消任务 60 while (!compositeCancel.IsCancellationRequested) 61 { 62 Console.WriteLine("C3"); 63 Thread.Sleep(1000); 64 } 65 } 66 } 67 }

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 //在使用可以Task类的Wait方法等待一个任务时或派生类的Result属性得到任务 7 //执行结果都有可能阻塞线程,为了解决这个问题能够使用ContinueWith方法, 8 //他能在一个任务完成时自动启动一个新的任务来处理执行结果。 9 namespace _6.ContinueWith方法在任务完成时启动一个新任务 10 { 11 class Program 12 { 13 static void Main(string[] args) 14 { 15 //建立一个任务 16 Task<int> task = new Task<int>(() => 17 { 18 int sum = 0; 19 Console.WriteLine("使用Task执行异步操做."); 20 for (int i = 0; i < 100; i++) 21 { 22 sum += i; 23 } 24 return sum; 25 }); 26 //启动任务,并安排到当前任务队列线程中执行任务(System.Threading.Tasks.TaskScheduler) 27 task.Start(); 28 Console.WriteLine("主线程执行其余处理"); 29 #region 解释这段的意思 30 //我来详细的解释下这个地方: 31 // 1.先明确上面Task建立的线程和主线程都在开始工做 32 // 2.我想获得Task任务运行结果,假如我直接写个方法输出它的结果 33 // 想象一下,假如Task任务还没结束你就要输出它的结果了 34 // 那结果能准确吗? 35 // 假如我不用方法输出它的结果,我建个线程来输出它的结果 36 // 想象一下,Task任务和新建的线程同时运行中, 37 // 一个在时时刻刻更新数据一个在时时刻刻读出它的数据