1.Microsoft.NET是基于Windows平台的一种技术(简称.NET),它包含了能在.NET Framework平台运行的所有语言。.NET Framework是微软为开发应用程序创建的一个具有革命性的新平台。
2. .NET.Framework也称.NET框架,是一个创建、部署、运行应用程序的多语言多平台环境、一套编程接口。
3..NET Framework的体系结构
4..NET Framework两个主要组件:
(1)公共语言运行时(CLR)Common Language Runtime
(2)统一的类库集(FCL)
5..NET的类库:
(1)基础数据的类库,例如String类、集合、泛函等
(2)文件输入/输出(I/O访问)
(3)数据库访问,ADO.NET组件
(4)XML解析
(5)安全控制,为.NET安全机制提供一系列功能
6.公共语言规范(CLS)
(1)规定所有.NET语言都应遵循的规则
(2)生成可与其他语言互操作的应用程序
VB.NET中命名是不区分大小写,而C#中则反之。
7.通用类型系统(CTS)
(1)包含标准数据类型
VB.NET的Integer和C#的int型都被编译成Int32.
CLS、CTS和MSIL紧密配合以实现语言互操作性
8.从控制台读入:
(1)Console.ReadLine(); //读取一行,返回值为string类型
(2)int.Parse(Console.ReadLine());//读取整数。。int.Parse表示字符串转换为整数。
9.从控制台输出:
(1)Console.WriteLine()方法----输出后换行
(2)Console.Write()方法-----输出后不换行
(3)特殊的形式:Console.WriteLine("格式字符串",变量列表);
例:string course="C#";
Console.WriteLine(“我的课程的名字是{0}”,course);
10.常用.NET Framework类库的命名空间
(1)System.Drawing 处理图形和绘画,包括打印
(2)System.Data 处理数据存储和管理,在定义ADO.NET技术中扮演重要角色
(3)System.IO 管理对文件和流的同步和异步访问
(4)System.Windows 处理基于窗体的窗口创建
(5)System.Reflection 包含从程序集读取元数据的类
(6)System.Threading 包含用于多线程编程的类
(7)System.Collections 包含定义各种对象集的接口和类
(8)System.Collections.Generic 包含泛型集合类
(9)System.Net 包含对网络协议进行编程的类
11.总结
(1).NET Framework由 .NET Framework 类库和公共语言运行时两个主要组件组成
(2)CLR是管理用户代码执行的现代运行时环境,它提供JIT编译、内存管理、异常管理和调试等方面的服务。
(3)CTS定义声明、定义和管理所有类型所遵循的规则,而无需考虑源语言
(4)CLS是所有针对.NET的编译器都必须支持的一组最低标准,以确保语言的互操作性
(5)命名空间是一组包含相关方面的相似类,专门用于避免类与类之间的名称冲突
(6)即时(JIT)编译器将MSIL代码编译为特定于目标操作系统和计算机体系的本机代码
12.常量在整个程序运行中保持不变的值。const关键字用于声明常量。
13.C#中的数据类型分为两个基本类型
(1)值类型
(I)内存中储存实际的有效数据
(II)int、char、结构、枚举等。
(2)引用类型
(I)内存中存储某数据对象的引用/地址
(2)为null,则表示为未引用任何对象
(3)类、接口、数据、字符串等。
14.数据类型转换:
(1)隐式转换:自动类型转换
当要把取值范围小的类型转换为取值大的类型时,C#自动会自动进行类型转换。
(2)显示转换:强制类型转换
与隐式转化相比,当要把取值范围大的类型转换为取值范围小的类型时,就需要在程序中用代码实现类型转换,否则会出错。
15.foreach循环用于遍历整个集合或数组
语法:
foreach(数据类型 元素(变量)in 集合或者数组)
{
//语句块
}
16.VS调试技巧
(1)断点(breakpoint):通知调试器应在某点上中断应用程序biang暂停执行
(2)监视(watch)窗口:计算变量和表达式的值
(3)调试常用快捷键:
(I)F5-----开始调试
(II)Shift+F5------停止调试
(III)F9-----设置或删除断点
(IV)F10----单步执行
17.获得数组的长度(元素的个数)数组名.Length
18.用二重循环实现冒泡排序算法
题目:依次比较相邻两数,如小的数在下层,则两数交换位置,否则两数保持原位。每轮结束后最小的数交换到最上层。
分析:(1)N个数字存放在一维数组中(2)外层循环控制比较多少轮,循环变量i(i<N-1)(3)内层循环控制每轮比较多少次,循环变量j(j<N-1-i)
代码示例:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
private static int[] GetSort(int[] array) { //外层循环n-1 for (int i = 0; i < array.Length-1; i++) { //内层循环n-1-i for (int j = 0; j < array.Length-1-i; j++) { if (array[j] > array[j+ 1]) { int temp = array[j]; array[j] = array[j + 1]; array[j + 1] = temp; } } }
19.六位随机数:
int num=new Random().Next(100000,1000000);
20.结构
(1)语法结构定义
访问修饰符 struct 结构名
{
定义结构成员
}
(2)含义
(I)自定义数据类型
(II)可在其内部定义属性、方法
(III)无法实现继承
(IV)属于值类型
(V)所有与Student关联的详细信息都可以作为一个整体进行储存和访问
(VI)定义成员变量不能赋初值
(3)结构的使用
(I)结构变量名.成员名
(II)结构变量名.方法名
21.枚举
(1)语法修饰符 enum枚举名
{
值1,值2,值3……
}
(2)含义
(I)枚举(Enum,Enumerator的缩写)是一组已命名的数值常量
(II)枚举定义具有一组特定值得数据类型
(III)对可能的值进行约束,不能包含方法
(IV)枚举允许描述性名称表示整数值
(V)C#中的枚举包含与值关联的数字
(VI)默认将0值赋给枚举的第一个元素,然后对每个后续的枚举元素按1递增
(VII)在初始化的过程中可重写默认值
(VII)枚举与其它类型的转换
public enum Color
{
Red=1,Blue=2,Green=3
}
(I)枚举转换为字符串
Console.WriteLine(“我喜欢的颜色是{0}.”,Color.Red.ToString());
(II)字符串转换为枚举
(Color)(Enum.Parse(typeof(Color),"Bule"))
22.C#常用的字符串处理方法
(I)bool Equals(string value) 比较一个字符串与另一字符串value的值是否相等。相等返回true,不等返回false。与“==”的作用一样
(II)int Compare(string strA,string strB) 比较两个字符串的大小关系,返回一个整数。如果strA小于strB,返回值小于0;如果strA等于strB,返回0。如果strA大于strB,返回值大于0
(III)int IndexOf(string value) 查找value字符在当前字符串中的第一个匹配的位置,找到value,就返回它的索引,找不到就返回-1
(IV)string Join(string separator,string[] value)把字符串数组value中的每个字符用指定的分隔符separator连接,返回连接后的字符串
(V)string [] Split(char separator)用指定的分隔符separator分割字符串,返回分割后字符串组成的数组。
(VI)string Substring(int startindex,int length)从指定的位置startindex开始检索长度为length的字符串
(VII)ToLower() 将字符串转换成小写形式
(VIII)ToUper() 将字符串转换成大写形式
(IX)Trim() 去掉字符串两边的空格
23.String 类的Format()方法用来格式化字符串
string myString=string.Format("格式字符串",参数列表);
24.方法中参数的值传递方式
(1)值传递: 只把参数的值传到方法里面,如果在方法中对参数的值进行了修改,在方法调用后,参数仍然持原值。方法中如对参数值进行了修改,方法调用后,参数仍保留原值。
(2)引用传递:按引用传递参数,可以在调用方法之后保留方法中对参数的修改。要想使参数按引用传递。需要使用ref关键字修饰参数。可在调用方法之后保留方法中对参数的修改。
25.String类型转换成其它类型: XXX.Parse()。其它类型转换成String类型:变量名.ToString()。任何类型之间的转换:Convert。
26。Windows窗口简介
(1)窗口:用户与应用程序之间进行交互的可视化界面。
(2)图形用户界面GUI(Graphical User Interface),又称图形用户接口,是指采用图形方式显示的计算机操作用户界面,与早期计算机使用的命令行界面相比,图形界面更易被用户接受。Windows窗口是典型的GUI界面。
(3)WinForms应用程序可能存在多个窗体,用户获取用户输入的数据和向用户显示数据。
27.C# Queue
(1)定义:System.Collections.Queue类表示对象的先进先出集合,存储在Queue(队列)中的对象在一端插入,从另一端移除。
(2)优点:
(I)能对集合进行顺序处理(先进先出)
(II)能接受null值,并且允许重复的元素
28.C#:由Microsoft公司推出,基于.Net Framework的面向对象的高级编程语言。
29.数组、数组链表ArrayList和List、Dictionary、SortedList、Hashtable
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
using System; using System.Collections.Generic;//数值链表的头文件 using System.Linq; using System.Text; using System.Collections;//数值链表的头文件 namespace ConsoleApplication1 { class Program { static void Main(string[] args) { int[] nmbers = new int[5]; string[,] names = new string[5, 4]; byte[][] scores = new byte[5][]; for (int i = 0; i < scores.Length; i++) { scores[i] = new byte[i + 3]; } for (int i = 0; i < scores.Length; i++) { Console.WriteLine("Length of row{0} is {1}", i, scores[i].Length); int[] nmbers2 = new int[5] { 1, 2, 3, 4, 5 }; string[,] name2 = { { "g", "k" }, { "dd", "eee" } }; int a = nmbers2.Length; // Console.ReadLine(); } ArrayList al = new ArrayList(); //数值链表 al.Add(5); al.Add(100); al.Remove(5); al.Add("dfdfdfdfdf"); foreach (var a in al) { Console.WriteLine(a); } Console.WriteLine(al[0]); List<int> intList = new List<int>();//数值链表 intList.Add(500);//增加 intList.AddRange(new int[]{501,502});//增加 Console.WriteLine(intList.Contains(200));//是否存在某个数值 Console.WriteLine(intList.IndexOf(501));//查找第一次出现某个值得位置 intList.Remove(501);//删除 intList.Insert(1,1001);//插入 Hashtable ht = new Hashtable();//哈希表 类型不规定 ht.Add("first","jike"); //键值 数值 ht.Add("second","xueyuan"); Console.WriteLine(ht[99]); //不存在一个键值 返回为空 Dictionary<string, string> d = new Dictionary<string, string>();// 类型规定 强类型 线程不安全。线程安全是ConcurrentDictionary 多字典 d.Add("first","jike"); //不在一个键值,会抛出一个异常 Console.WriteLine(ht["second"]); SortedList<int, int> s1 = new SortedList<int, int>();//根据键值 排序 跟值大小、增加的顺序无关 s1.Add(5,105); s1.Add(2, 1025); s1.Add(4, 1055); s1.Add(6, 1015); s1.Add(7, 1005); s1.Add(51, 1035); s1.Add(35, 1095); foreach (var sle in s1) { Console.WriteLine(sle.Value);//可以键值和值进行 } //stack栈,queue队列 Console.ReadLine(); } } }
30.在计算机中,每一个程序运行的时候,操作系统都会为它分配一个进程,而线程正是进程的组成单位。线程是程序中独立的指令流,在操作系统中,一个进程至少要包含一个线程。
31.并发:同时做多件事情。
32.多线程:并发的一种形式,它采用多个线程来执行程序。多线程是并发的一种形式,但不是唯一的形式。
33.线程池存放任务的队列,这个队列能够根据需要自行调整。相应地,线程池产生了另一个重要的并发形式:并发处理。并发处理:把正在执行的大量的任务分割成小块,分配给多个同时运行的线程。
34.异步编程:并发的一种形式,它采用future模式或回调(callback)机制,以避免产生不必要的线程。
35.异步编程的核心理念是异步操作:启动了的操作将会在一段时间后完成。
36.响应式编程: 一种声明式的编程模式,程序在该模式中对事件做出响应。
37.异步编程有两大好处:第一个好处是对于面向终端用户的GUI程序:异步编程提高了响应能力。第二个好处是对于服务器端应用:异步编程实现了可扩展性 。
38.现代的异步.NET程序使用两个关键字:async和await。
39.并行的形式有两种:数据并行(data parallelism)和任务并行(task parallelism)。
40.数据流网格的基本组成单元是数据流快(dataflow block)。
41.指数退避是一种重试策略,重试的延迟时间会逐次增加。在访问Web服务器时,最好的方式就是采用指数退避,它可以防止服务器被太多的重试阻塞。
42.在用同步代码实现异步接口时,要避免使用任何形式的阻塞操作。在异步方法中进行阻塞操作,然后返回一个完成的Task对象,这种做法并不可取。
43.IP地址操作类:
(1)IPAddress类
a.在该类中有一个Parse()方法,可以把点分的十进制IP表示转化成IPAddress类,
方法如下:IPAddress address=IPAddress.Parse("192.168.0.1");
b.IPAddress提供4个只读字段
(I)Any:用于代表本地系统可用的任何IP地址。
(II)Broadcase:用于代表本地网络的IP
(III)Loopback:用于代表系统回送地址
(IV)None 用于代表系统上没有网络接口
44.Thread类
(1)在.NET Framework类库中,多线程的功能被包含在System.Threading命名空间中。因此,要使用多线程,必须先声明引用此命名空间。在这个命名空间中,提供了一些方法,可用于对线程进行的基本操作。例如:启动线程的执行、终止、唤醒等。
(2)Thread类的ThreadState属性可以判断线程的当前状态。线程有7个状态,它们是:born(新生)、runnable(可运行)、running(运行)、waiting(等待)、sleeping(睡眠)、Blocked(阻塞)、dead(死亡)。
(3)有两种方式可以给线程传递数据。第一种方式是使用带委托参数的Thread类构造函数。另一种方式是程序员自己创建一个类,把线程的方法定义为实例方法,这样就可以初始化实例的数据,然后就可以用Start()方法启动线程了。
(4)由于为线程传送的数据是存储在类或者结构中的,所以在传送数据之前,需要定义一个存储数据的类或者结构。
(5)操作系统在调度多线程的时候。会给每个线程指定不同的优先级,这样就可以影响调度的顺序,这个过程就像运算符的优先级一样。在Thread类中,通过设置Priority属性来定义基本优先级。
(6)ThreadPriority类枚举线程优先级的所有可能值
(I)AboveNormal:在具有Highest优先级的线程之后,具有Normal优先级的线程之前
(2)BelowNormal:在具有Normal优先级的线程之后,具有Lowest优先级的线程之前
(3)Highest:在具有任何其他优先级的线程之前。
(4)Lowest:在具有任何其他优先级的线程之后
(5)Normal:在具有AboveNormal优先级的线程之后,在具有BelowNormal优先级的线程之前。默认情况下,初始分配的线程具有Normal优先级。
(7)使用多线程编程会带来一些问题,例如:把两个线程竞争资源、单个线程进行死锁循环等。在术语中,把这两种现象叫做线程的静态和死锁。
(8)竞争条件就是两个或多个线程访问形同的资源对象,或者相互之间访问不同步的共享状态。
(9)在两个线程中,线程A抢到了资源1,还需要资源2;线程B抢到了资源2,还需要资源1。那么必然会产生死锁。在死锁中,至少有两个线程被挂起,等待对方解除锁定。由于两个线程都在等待对方,就出现了死锁,线程将无限等待下去。
(10)由于线程的优先级是动态分配的,所以程序员也无法知道启动的线程是哪一个先执行。如果有某一个线程一直需要使用CPU,而且又不等待资源,那么它的优先级就会降低。如果某一个线程在等待资源,那它的优先级向上就会增加。但是如果为每个线程指定了优先级后,就可以对它进行控制了。
45.线程分为前台线程和后台线程,差别就在于是否会阻止主线程结束。
46.线程异步是多线程同步执行,线程同步是在多线程遇到抢夺资源的时候防止多个线程打架。
47.实例化Thread类的时候可以使用委托类有两个,分别是由参数和无参数。
48.几个同样的线程,如果希望被优先执行,则需要为其设置优先级。
49.暂停线程有堵塞、挂起、join等几种方式。
50.AutoResetEvent是线程实现通知操作的重要方法。通常,AutoResetEvent用于通知正在等待线程已发生事件,允许线程通过发送信号互相通信。
51.AutoResetEvent事件对象提供给了我们这样的通知机制,让我们可以控制线程执行的先后顺序,它的常用方法如下:
(1)Set:设置并发送信号
(2)Reset:设置信号,也就是使信号无效
(3)WaitOne:等待一个信号,如果没有信号到来则等待
(4)WaitAny:静态方法,等待一个信号数组,信号数组里面有任何信号到都可以,否则等待。
(5)WaitAll:静态方法,等待一个信号数组,信号数组里面的信号全部到齐才可以,否则等待。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
//C#提供的泛型类似C++中的模板,下面是一个实例,结合泛型和反射功能,可以使我们通过字符串查找类中的变量成员,并赋值。这个功能非常有用,比如当我们从数据库或XML文件中读取数据的时候,即可以通过字段名称赋值,实现自动序列化 /* String.Format方法 将指定字符串中的每个格式项替换为相应对象的值的文本等效项 */ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication7 { class Program { static void Main(string[] args) { //创建一个Player对象 Player p = new Player(); //通过字段名称给Player对象复制 SetObjectValue<Player>(p,"name","goodman"); SetObjectValue<Player>(p, "id", 100); Console.WriteLine(string.Format("name:{0},id:{1}",p.name,p.id)); Console.ReadLine(); } //一个Player类,它包括名称为name和id两个成员 public class Player { public string name = string.Empty; public int id = 0; } //一个使用了泛型的函数,<T>是泛型参数,它可以是任何类型的对象‘ public static void SetObjectValue<T>(T obj, string fieldname, object value) { //通过字段名称获得对象的成员变量 System.Reflection.FieldInfo info = obj.GetType().GetField(fieldname); if (info != null) { //给成员变量赋值 info.SetValue(obj,value); } } } }
53.字符串学习总结
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
///C#字符串是使用string关键字声明的一个字符数组,它也是一个对象,封装了所有字符串操作,如比较、插入、删除、查找等。 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { //创建一个字符串 string str1 = "apple orange banana"; Console.WriteLine("str1:+str1"); ///创建另一个字符串 string str2 = str1 + "peach"; Console.WriteLine("str2:" + str2); //比较两个字符串是否一致 if (String.Compare(str1, str2) == 0) { Console.WriteLine("str1 和str2两个字符串一致"); } else { Console.WriteLine("str1和str2两个字符串不一致"); } //从第0个字节开始查找空格的位置 int n=str1.IndexOf(' ',0); Console.WriteLine("str1第一个空格在第{0}个字节",n); ///删除第1个空格之后的所有字符 str2=str1.Remove(n); Console.WriteLine("删除str1第一个空格后的所有字符:"+str2); ///将所有空格替换为- str2=str2.Replace(' ','-'); Console.WriteLine("将所有的空格替换为-:"+str2); ///在第一个空格之后插入@@@ str2=str1.Insert(n,"peach"); Console.WriteLine("在str1第一个空格插入peach:"+str2); ///取第一个空格后的6个字符 str2=str1.Substring(n+1,6); Console.WriteLine("取str1第一个空格后的6个字符:"+str2); ///以空格为标记,将字符串分解为若干个新的字符串 char[]chars={' '}; string[]strs=str1.Split(chars); Console.WriteLine("以空格为标识符,将str1分解为:"); for(int i=0;i<strs.Length;i++) Console.WriteLine(i+":"+strs[i]); ///按任意键退出 Console.ReadKey(); } } }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
using UnityEngine; using System.Collections; public class UserRegister : MonoBehaviour { void Start () { string s = " http://www.taikr.com "; print(s); string s1=s.Trim();//Trim()去掉两端的空格。 print(s1); string s2 = "http://www.takir.com"; int index=s2.IndexOf("takir");//Index0f(string str)返回str的位置,匹配第一个。 print(index);//结果11,从零开始数,不存在则为-1 string s3 = "Siki is a good man,he singing good!"; int index1=s3.LastIndexOf("good");//LastIndexOf(string str);返回最后一个匹配 print(index1);//30,不存在则为-1 } }
54.base的学习:
(1)base关键字用于从派生类中访问基类的成员:
(I)调用基类上已被其他方法重写的方法
(II)指定创建派生类实例时应调用的基类构造函数
(2).基类访问只能在构造函数、实例方法或实例属性访问器中进行
(3).从静态方法中使用base关键字是错误的。
55.readonly关键字学习总结:
(1)readonly关键字是可以在字段上使用的修饰符。当字段生命包括readonly修饰符时,该声明引入的字段赋值只能作为声明的一部分出现,或者出现在同一类的构造函数中
(2)在此实例中,字段year的值无法再ChangeYear方法中更改,即使在类构造函数中中给它赋了值。
(3).只能在下列上下文中对readonly字段进行赋值:
(I)当在声明中初始化变量时,例如:public readonly int y=5;
(II)对于实例字段,在包含字段声明的类的实例构造函数中;或者,对于静态字段,在包含字段声明的类的静态构造函数中。也只有在这些上下玩中,将readonly字段作为out或ref参数传递有效。
(III)readonly 关键字与const关键字不同。const字段只能在该字段的声明中初始化。readonly字段可以在声明或构造函数中初始化。因此,根据所使用的构造函数,readonly字段可能具有不同的值。另外,const字段为编译时常数,而readonly字段可用于运行时常数,如下例所示:
public static readonly uint timeStamp=(uint)DateTime.Now.Ticks;
(4)
在前面的示例中,如果使用这样的语句:
p2.y = 66; // Error
将收到编译器错误信息:
The left-hand side of an assignment must be an l-value
这与尝试将值赋给常数时收到的错误相同。
56.线程的基本知识
(1)线程有时被称为轻量级进程,是程序执行流的最小单元。
(2)线程是由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。
(3)线程自身不能拥有系统资源,但是可以使用线程所属进程所占有的系统资源。
(4)线程可以创建和撤销另一个线程。
(5)线程可以拥有自身的状态,例如 运行状态,挂起状态,销毁释放状态等等。
(6)线程具有优先级,每个线程都分配了0-31级别的其中一个优先级,数字越大,优先级越高,然后手动分配优先级过于复杂,所以微软为我们的Thread类提供一个优先级的枚举,ThreadPriority枚举便是优先级枚举,我们可以利用thread.Priority属性来进行设置
57.多线程有什么实际好处呢?
首先我们了解多线程的概念:一个程序或者进程中同时运行多个线程完成不同的工作。
从概念中我们便可知道多线程的优缺点了
(1)能够实现并行操作,也就是说多个线程可以同时进行工作
(2)利用多线程后许多复杂的业务或者是计算可以交给后台线程去完成,从而提高整体程序的性能
(3)类似于第一条利用多线程可以达到异步的作用(注意,实现异步的一种方式是多线程)
58.线程同步
关于线程同步的概念最简单的理解就是同步方法调用在程序继续之前,需要等待同步方法执行完毕返回结果。很有可能多个线程都会对一个资源进行访问,从而导致资源被破坏,所以必须采用线程的同步机制,例如共享资源加锁,当其中一个线程占有了锁定之后,其余线程均不能使用共享资源,只有等其释放资源之后,接下来的其中一个线程会占该锁。
59.线程异步
线程异步指的是一个调用请求发送给被调用者,而调用者不用等待其结果的返回,一般异步执行的任务都需要比较长的时间,所以为了不影响主线程的工作,可以使用多线程或者新开辟一个线程来实现异步,同样,异步和线程池也有非诚紧密的联系。
60.前台线程:
诸如我们Console程序的主线程,wpf或者sliverlight的界面线程等等,都属于前台线程,一旦前台线程崩溃或者终止,相应的后台线程都会终止,本章中通过Thread类产生的线程默认都是前台线程,当然我们可以设置Thread的属性让该对象成为后台线程,必须注意的是,一旦前台线程全部运行完毕,应用程序的进程也会释放,但是假设Console程序中main函数运行完毕,但是其中几个前台线程还处于运行之中,那么这个Console程序的进程是不会释放的,仍然处于运行之中,直到所有的前台线程都释放为止。
61.后台线程:
和前台线程唯一的区别是,后台线程更加默默无闻,设置后台线程因某种情况,释放销毁时不会影响到进行,也就是说后台线程释放时不会导致进程的释放。
62.细说下Thread最为关键的构造函数:
开始对Thread这个线程类进行深层次的研究下,首先要启动一个线程必须将该线程将要做的任务告诉该线程,否则,线程会不知道干什么导致线程无意义的开启,浪费系统资源,果然,Thread类的构造函数提供了以下的版本:
(1)Thread(ParameterizedThreadStart):初始化Thread类的新实例,指定允许对象在线程启动时传递该线程的委托。
(2)Thread(ThreadStart):初始化Thread类的新实例。
ThreadStart和ParameterThreadStart参数都是委托,所以可以看出委托其实就是方法的抽象,前者用于不带参数的并且无返回值得方法的抽象,后者是带object参数的方法的抽象,可以通过以下简单的方法注意线程如何调用带参数的方法。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
不带参数方法似乎很简单的能调用,只要通过第一个构造函数便性,对于带参数的方法,大家注意下参数是如何传入线程所调用的方法,当启动线程时,参数通过thread.Start方法传入,于是我们便成功启动了thread线程。
63.细说下Thread的join方法
在细说前我想再次强调下主主线程和子线程的区别:
首先大家肯定知道在Console程序中,主线程自上而下运行着main函数,假如我们在main函数中新增一个线程thread对象的话,也就是说,在线程中再开启一个子线程,同时子线程和主线程可以同时工作(前提是子线程使用Start方法),同理,假如我在这个子线程中再开辟一个属于这个子线程的子线程,同理这3个 爷爷、父亲、儿子线程也可以使用Start()方法一起工作,假如在主线程中添加2个thread对象并开启,那么这2线程便属于同一层次的线程(兄弟线程)(和优先级无关,只同一位置层次上的兄弟)。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
64.细说下Thread的Abort和Interrupt方法
Abort方法:
其实Abort方法并没有像字面上的那么简单,解释并终止调用线程,其实当一个线程调用Abort方法时,会在调用此方法的线程上引发一个异常“
ThreadAbortException。
Interrupt方法:
Interrupt方法将当前的调用该方法的线程处于挂起状态,同样在调用此方法的线程上引发一个异常:ThreadInterruptedException,和Abort方法不同的是,被挂起的线程可以唤醒。
65.细说下Thread的Suspend,Resume方法
Suspend和Resume方法,前者将当前运行的线程挂起,后者能够恢复当前被挂起的线程。
66.简单了解下Thread的一些常用的重要属性
(1)CurrentThread:获取到当前线程的对象
(2)IsAlive:判断线程是否处于激活状态
(3)IsBackground:设置该线程是否是后台线程,一旦设置true的话,该线程就被标示为后天线程。后台线程的终止不会导致进程的终止。
(4)IsThreadPoolThread:只读属性标示该线程是否属于线程池的托管,一般我通过线程池创建的线程该属性都是true。
(5)Name:获取到线程的名字,我们可以根据业务或者逻辑来自定义线程的名字
(6)Priority:这个属性标示线程的优先级,我们可以用ThreadPriority这个枚举来设置这个属性。
67.进程和线程的概念:
(1)进程:是一个具有一定独立功能的程序关于某个数据集合的一次活动。它是操作系统系统执行的基本单元,在传统的操作系统中,进程即使基本的分配单元,也是基本的执行单元。
(2)线程:是”进程“中某一个顺序的控制流。
68.进程
framework里面对”进程“的基本操作的封装还是蛮好的,能够满足我们实际开发中的基本应用。
<1>获取进程信息
framework中给我们获取进程的方式还是蛮多的,即可以按照Name获取,也可以按照ID获取,也可以获取本地和远程的进程信息。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
<2>启动和停止进程
Process 中的”kill“和”CloseMainWindow“的区别:
windowMianWindow:当我们打开的Process是一个有界面的应用程序时,推荐使用此方法,它相当于点击了应用程序的关闭按钮,是一个有序的终止应用程序的操作,而不行kill那么暴力。
kill:它的作用就是强制关闭我们打开的Process,往往会造成就是我们数据的丢失,所以说在万不得已的情况下不要使用kill,当然在无图形界面的应用程序中,kill是唯一能够结束Process的一个策略。
14.线程
同样线程的相关操作也已经被framework里面的Thread完美的封装,大大简化了我们的工作量,常常的操作如下:
<1>启动线程
<2>终止线程
<3>暂停线程
<4>合并线程
比如:t1线程在执行过程中需要等待t2执行完才能继续执行,此时我们就要将t2合并到t1中去,也就是在t1的代码块中写上t2.Join()即可。同样Join中也可以加上等待t2执行的时间,不管t2是否执行完毕。
<5>线程同步
多线程解决了系统的吞吐量和相应时间,同时也给我们留下了比如死锁,资源争用等问题,那么我们如何解决这些实际问题呢?当然会有很多的实现同步线程的类,比如Mutex、Monitor、Interlocked和AutoResetEvent,当然在实际应用中,我们还是喜欢使用简化版的lock,因为会使编程简化,同时使程序看起来简洁命了。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
<6>线程池
在某些实际应用中,Client端的每个请求Server都需要创建一个线程来处理,那么当线程很多的时候并不是一件好事情,这会导致过度的使用系统资源而耗尽内存,那么自然就会引入"线程池";
线程池:线程池也有最大线程数限制,大小在不同的机器上是否区别的,当池中的线程都是繁忙状态,后人的方法就会排队,直至池中有空闲的线程来处理。
69.同步套接字通信
Socket支持下的网上点对点的通信
服务器实现监听连接,客户端实现发送连接请求,建立连接后进行发送和接受数据的功能。
服务器端建立一个socket,设置好本机的ip和监听的端口与socket进行绑定,开始监听连接请求,当接收到连接请求后,发送确认,同客户端建立连接,开始于客户端进行通信。
客户端建立一个socket,设置好服务器端的ip和提供服务的端口,发送连接请求,接收到服务的确认后,尽力连接,开始于服务器进行通信。
服务器端和客户端的连接及它们之间的数据传送均采用同步方式。
70.Socket
Socket是tcp/ip网络协议接口。内部定义了许多的函数和例程。可以看成是网络通信的一个端点。在网络通信中需要两个主机或两个进程。通过网络传递数据,程序在网络对话的每一端需要一个socket。
Tcp/Ip传输层使用协议端口将数据传送给一个主机的特定应用程序,协议端口是一个应用程序的进程地址。传输层模块的网络软件模块要于另一个程序通信,它将使用协议端口,socket是运行在传输层的api,使用socket建立连接发送数据要指定一个端口给它。
Stream Socket流套接字 Socket提供双向、有序、无重复的数据流服务,出溜大量的网络数据。
Dgram socket数据包套接字 支持双向数据流,不保证传输的可靠性、有序、无重复。
Row socket 原始套接字 访问底层协议
建立socket (用C#)
命名空间:using System.Net;using System.Net.Socket;
构造新的socket对象:socket原理:
public socket(AddressFamily addressFamily,SocketType sockettype,ProtocolType protocolType)
AddressFamily:用来指定socket解析地址的寻址方案。Inte.Network标示需要ip版本4的地址,Inte.NetworkV6需要ip版本6的地址。
SocketType参数指定socket类型Raw支持基础传输协议访问,Stream支持可靠,双向,基于连接的数据流。
ProtocolType表示socket支持的网络协议
71.定义主机对象:
IPEndPoint类:IPEndPoint构造方法
位置:System.Net
原型:1)public IPEndPoint(IPAddress address,int port)
2)public IPEndPoint(long address,int port)
主机解析:
利用DNS服务器解析主机,使用Dns.Resolve方法
原型:public static IPHostEntry Resolve(string hostname)参数:待解析的主机名称,返回IPHostEntry类值,IPHostEntry为Inte.Net主机地址信息提供容器,该
72.什么是委托:
C#委托相当于C/C++中的指针,函数指针用指针获取函数的入口地址,实现对函数的操作。与其不同的是,委托是面向对象的,类型安全的和保险的。因此需要经过定义、声明并实例化之后才可以使用它。使用时作为参数进行传递,为引用传递。委托的实例化中的参数(要委托的方法)即可以是实例方法,也可以是静态方法。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
package com.imooc.io; public class EncodeDemo { /** * @param args */ public static void main(String[] args)throws Exception{ // TODO Auto-generated method stub String s="慕课ABC"; byte[] bytes1=s.getBytes();//转换成字节序列用的是项目默认的编码gbk for(byte b:bytes1) { //把字节(转换成了int)以16进制的方式显示 System.out.print(Integer.toHexString(b&0xff)+" "); } System.out.println(); byte[]bytes2=s.getBytes("gbk"); //gbk编码中文占用2个字节,英文占用1个字节 for(byte b:bytes2) { //把字节(转换成了int)以16进制的方式显示 System.out.print(Integer.toHexString(b&0xff)+" "); } System.out.println(); byte[]bytes3=s.getBytes("utf-8"); //utf-8编码中文占用3个字节,英文占用1个字节 for(byte b:bytes3) { //把字节(转换成了int)以16进制的方式显示 System.out.print(Integer.toHexString(b&0xff)+" "); } System.out.println(); //Java是双字节编码 utf-16be byte[]bytes4=s.getBytes("utf-16be"); //utf-16be中文占用2个字节,英文占用2个字节 for(byte b:bytes4) { //把字节(转换成了int)以16进制的方式显示 System.out.print(Integer.toHexString(b&0xff)+" "); } //当你的字节序列是某种编码时,这个时候想把字节序列变成字符串, //也需要用这种编码方式,否则会出现乱码 String str1=new String(bytes4);//用项目默认的编码 System.out.println(str1); String str2=new String(bytes4,"utf-16be");//用项目默认的编码 System.out.println(str2); //文本文件 就是字节序列 可以是任意编码的字节序列 //如果我们在中文机器上直接创建文本文件,那么该文本文件只认识ansi编码 //联通、联这是一种巧合,他们正好符合了utf-8编码的规则. } }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
IEnumerator StartRightLiziCard()//在下面函数的调用开始执行 { yield return new WaitForSeconds(1.0f);//等待1秒针 areas[Index].energyGun.SetActive(true);//执行 } int Index = 1; public void playEnergyGun(int seatIndex, bool isPlay)//开始执行 { if (isPlay) { if (areas[seatIndex - 1].isEnergyOver) { areas[seatIndex - 1].isEnergyOver = false; Index = seatIndex - 1; StartCoroutine("StartRightLiziCard");此处执行到上面函数的接口。。。但是同时向下面代码执行。。 int spriteName = Convert.ToInt32(areas[seatIndex - 1].gunBarrel.GetComponent<UISprite>().spriteName); areas[seatIndex - 1].gunBarrel.GetComponent<UISprite>().spriteName = (spriteName + 4).ToString(); areas[seatIndex - 1].particle.Play(); } } else { if (!areas[seatIndex - 1].isEnergyOver) { areas[seatIndex - 1].isEnergyOver = true; areas[seatIndex - 1].energyGun.SetActive(false); int spriteName = Convert.ToInt32(areas[seatIndex - 1].gunBarrel.GetComponent<UISprite>().spriteName); areas[seatIndex - 1].gunBarrel.GetComponent<UISprite>().spriteName = (spriteName - 4).ToString(); areas[seatIndex - 1].particle.Play(); } } } 注意:相当于开启了一个子线程,但是主线程仍向下执行。
76 为了避免每次都使用锁,有一个传统的方式叫做双重锁定(double-checked locking)模式 。
77如果惰性求值的对象实现是线程安全的,并不自动说明它的所有属性也是线程安全的。
78Map/Reduce功能是另一个重要的并行编程模式。它适用于小程序,及拥有大量的多个服务器端计算的场景。该模式的含义是你有两个特殊的功能要应用于你的数据。其中第一个是Map函数。它接收一组键/值得初始数据,并产生另一组键/值序列,将初始数据转为适合的格式以便进行下一步处理。然后我们使用另一个叫做Reduce的函数。Reduce函数使用Map函数的结果,并将其转化为我们需要真正的尽可能小的数据集。
79.Windows Communication Foundation(简称WCF)是一个框架,用于以不同的方式调用远程服务。其中一个有一段时间非常流行,用于通过HTTP使用基于XML的协议来调用远程服务,它叫做简单对象方位协议(Simple Object Access Protocol,简称SOAP)。
80.并发:同时做多件事情
81.多线程:并发的一种形式,它采用多个线程来执行程序。
82.线程池存放任务的队列,这个队列能够根据需要自行调整。相应地,线程池产生了另一个重要的并发形式:并行处理。
83.并行处理:把正在执行的大量的任务分割成小块,分配给多个同时运行的线程。
84.异步编程:并发的一种形式,它采用future模式或回调(callback)机制,以避免产生不必要的线程。(基于异步 操作)
85.异步编程的核心理念是异步操作:启动了的操作将会在一段时间后完成。这个操作正在执行时,不会阻塞原来的线程。启动了这个操作的线程,可以继续执行其他任务。当操作完成时,会通知它的future,或者调用回调函数,以便让程序知道操作已经结束。
86.并发编程的另一种形式是相应式编程。
87.响应式编程:一种声明式的编程模式,程序在该模式中对事件做出响应。(基于异步事件)
88.异步编程有两大好处:第一个好处是对与面向终端用户的GUI程序:异步编程提高了响应能力。第二个好处是对于服务器应用:异步编程实现了可扩展性。
89. async关键字加在方法声明上,它的主要目的是使方法内的await关键字生效。如果async方法有返回值,应返回Task<T>;如果没有返回值,应返回Task。这些task类型相当于future,用来在异步方法结束时通知主程序。
90.一个async方法是由多个同步执行的程序块组成的,每个同步程序块之间由await语句分割。
91.并行的形式有两种:数据并行和任务并行。数据并行是指有大量的数据需要处理,并且每一块数据的处理过程基本上是彼此独立的。任务并行是指需要执行大量任务,并且每个任务的执行过程基本上是彼此独立的。
92.实现数据并行有几种不同的做法。一种做法是使用Parallel.ForEach方法。另一种做法是使用PLINQ(Parallel LINQ),它为LINQ查询提供了AsParallel扩展。
93.数据流网格的基本组成单元是数据流块。