多线程&网络编程
1、多线程:

    线程:是操作系统分配处理器时间的基本单元,并且进程中可以有多个线程同时执行代码。
    NET用Thread创建并控制线程,设置做强先级并获取其状态。
        Thread t1 = new Thread(new ThreadStart(tt1.WriteColor));
            或
        Thread t1 = new Thread(new ParameterizedThreadStart(tt1.WriteColor));
注:object数组可以赋给object类型的变量,数组继承Array,Array又继承object,即用子类来实例化父类是可以的,而int或其他类型的数组不具有这样的属性。
例:
        static void Main(string[] args)
        {
            ThreadStart st = new ThreadStart(F1);
            Thread th1 = new Thread(st);//多线程的两种声明方法之一
            th1.Start();
            Thread th2 = new Thread(F2);//第二种多线程的声明方法
            object[] obj = new object[] { "1",33,1,8,2.5,1};
            object o = obj;//将object的数组赋值给object类型的变量o
            th2.Start(o);//多线程有两种参数,一种是无参,一种是object类型的参数
               
        }
        static void F1()
        { 
            Console.WriteLine("387447647646");           
        }
        static void F2(object o)
        {
            foreach (object obj in (object[])o)
            {
                Console.WriteLine(obj);
            }//将object类型的参数转换成object数组并遍历输出数组元素
        }
上例中多线程有两种声明方法:
       
            1)ThreadStart st = new ThreadStart(F1);//F1方法
               Thread th1 = new Thread(st);//多线程的两种声明方法之一
            2) Thread th2 = new Thread(F2);//第二种多线程的声明方法,F2为方法
 
小练习1:用线程的join()方法实现一个线程的加入终止另一个线程的操作
                 阻塞线程
  class Program
    {
        static Thread ThrTest1, ThrTest2;
        static void Main(string[] args)
        {
            ThreadStart TS1 = new ThreadStart(WriteLine1);
            ThrTest1 = new Thread(TS1);
            ThreadStart TS2 = new ThreadStart(WriteLine2);
            ThrTest2 = new Thread(TS2);
            ThrTest1.Start();
            ThrTest2.Start();
        }
        public static void WriteLine1()
        {
            for (int i = 0; i < 20; i++)
            {
                if (i == 10)
                {
                    ThrTest2.Join();
                }
                Console.ForegroundColor = ConsoleColor.Blue;
                Console.WriteLine(i.ToString() + "WriteLine1");
                Thread.Sleep(500);
            }
        }
        public static void WriteLine2()
        {
            for (int i = 0; i < 20; i++)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine(i.ToString() + "WriteLine2");
                Thread.Sleep(500);
            }
        }
   
}
小练习2:利用lock()代码段实现线程的同步控制(例火车票的同步售出)
     class Program
     {
       static void Main(string[] args)
        {
            BookShop a = new BookShop();
            Thread t1 = new Thread(new ThreadStart(a.Sale));
            Thread t2 = new Thread(new ThreadStart(a.Sale));
            t1.Start();
            t2.Start();
        }
     }
       public class BookShop
        {
            int num = 1;//共享资源
            public void Sale()
            {
                lock (this)//同步控制
                {
                    if (num > 0)
                    {   //卖书过程
                        Thread.Sleep(1000);
                        num = num - 1;
                        Console.WriteLine("售出一本");
                    }
                    else
                    {
                        Console.WriteLine("没有了");
                    }
                }
            }
        }

Monitor 类通过向单个线程授予对象锁来控制对对象的访问,对象锁提供限制访问代码块(通常称为临界区)的能力。
2、网络编程:
TCP/IP(Transmission Control Protocol/Internet Protocol)的简写,中文译名为传输控制协议/网际协议,又叫网络通讯协议,这个协议是Internet最基本的协议、Internet国际互联网络的基础,简单地说,就是由网络层的IP协议和传输层的TCP协议组成的。
TCP/IP 是供已连接因特网的计算机进行通信的通信协议。
 
在.net中,我们用TCPClient和TCPListener类来实现点对点通讯,这两个命名空间位于此System.Net.SocketsTcpListener 类提供一些简单方法,用于在阻止同步模式下侦听和接受传入连接请求。可使用 TcpClient 或 Socket 来连接 TcpListener。可使用IPEndPoint、本地 IP 地址及端口号或者仅使用端口号,来创建 TcpListener。
TcpClient 类提供了一些简单的方法,用于在同步阻止模式下通过网络来连接、发送和接收流数据。
 
小练习:网络编程实现客户端与服务器端的相互通信(一个服务器端可同时与多个客户端端通信)。
   
      思路总结:1)要想实现一个服务器与多个客户端通信可以用一个泛型的哈希表来保存服务器监听到得客户端的信息,包括客户端的代号(用键保存代号)和客户端的流,每次服务器端可以选择要通信的客户端,利用检索保存客户端信息的哈希表来选择。
                2)在服务器端有一个可以接收所有客户端的方法,分别将接收到得信息保存在哈希表中。
 
   具体实现如下:
 
 服务器端:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using System.Collections ;
namespace Server
{
    class Program
    {
        static Dictionary<string, NetworkStream> clients = new Dictionary<string, NetworkStream>();
        static void Main(string[] args)
        {
            Console.WriteLine("server");
            TcpListener server = new TcpListener(IPAddress.Parse("192.168.0.105"), 9999);//定义一个服务器 监听网络的客户端
            server.Start();
            Thread th = new Thread(Accept );//定义一个线程,执行Accept方法,传递一个参数是接收到得网络流,不断接收所挂起的链接请求
            th.Start(server);//将当前定义的服务器发送给Accept方法接收所有的客户端           
            Console.WriteLine("开始发送请按任意键!");
            Console.ReadLine();
            while (true)
            {
                foreach (string key in clients.Keys)
                {
                    Console.WriteLine("{0}", key);
                }//将哈希表中已保存的客户端信息打印出来供用户选择
                Console.WriteLine("请输入编号选择您要对话的客户端:");
                string index = Console.ReadLine();
                NetworkStream netstream = clients[index];//根据用户输入信息转换为哈希表的键,然后根据键取出哈希表中存放的制定客户端的流信息,以便进行写操作
                StreamWriter sw = new StreamWriter(netstream);//定义一个写文件流执行写操作
                while (true)
                {
                    Console.WriteLine("请输入发送内容:");
                    string con = Console.ReadLine();
                    sw.WriteLine(con);//将要发送的内容写入流中供客户端读取
                    sw.Flush();//清理当前编写器的缓冲区
                    Console.WriteLine("退出请按E,继续请按任意键!");
                    if (Console.ReadLine().ToUpper() == "E")
                    {
                        break;
                    }
                }//定义一个死循环像客户端发送消息
            }
        }
        /// <summary>
        /// 读取客户端发过来的消息
        /// </summary>
        /// <param name="o"></param>
        static void ReadText(object o)
        {
            NetworkStream netstream = o as NetworkStream;
            StreamReader sr = new StreamReader(netstream);
            while (true)
            {
                Console.WriteLine("--------------------");
                string con = sr.ReadLine();
                //string [] a=con.Split('|');
                //foreach(string key in clients.Keys )
                //{
                //    if (a[0] == key)
                //    {
                //        NetworkStream netstream1 = clients[key];
                //    }
                   
                //}
              
                Console.WriteLine(con);
                Console.WriteLine("客户端:"+DateTime.Now );
                Console.WriteLine("--------------------");
            }
         
        }
        /// <summary>
        /// 获取所有登入服务器的客户端,并将其代号和流信息保存在泛型哈希表中
        /// </summary>
        /// <param name="o"></param>
        static void Accept(object o)
        {
            TcpListener server = o as TcpListener;
            while (true)
            {
                TcpClient client = server.AcceptTcpClient();//接收挂起的连接请求,服务端每接收一个客户端消息都会生成
                NetworkStream netstream = client.GetStream();//获取客户端的流
                StreamReader sr = new StreamReader(netstream );
                string con=sr.ReadLine();//获取客户端流输入的一行数据,即唯一标识某个客户端的数据,将其保存为泛型哈希表的键
                clients.Add(con,netstream );//将唯一标识客户端的数据和该客户端的流保存在哈希表中
                Thread th = new Thread(ReadText);//定义一个进程,调用ReadText 方法,读取客户端输入的内容
                th.Start(netstream);//调用线程利用流读取客户端发来的数据内容
            }//循环让服务器不断地接收客户端
        }
    }
}
 
客户端:    

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
namespace Client
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("client");
            TcpClient client = new TcpClient("192.168.0.105", 9999);//客户端链接,存放的是服务器端的IP地址
            NetworkStream netstream = client.GetStream();//客户端接收到的网络流
            StreamWriter sw = new StreamWriter(netstream);
            Console.WriteLine("请输入客户端信息:");
            Thread th = new Thread(ReadText);//定义一个线程,执行ReadText方法,读网络流发送过来的消息,如果有发送来的消息就触发该线程,如果没有则跳过接着往下执行
            th.Start(netstream);
            while (true)
            {
                string con = Console.ReadLine();
                sw.WriteLine(con);//将用户要发送的内容写进流供服务器端读取
                sw.Flush();//将客户端信息发送给服务器
                Console.WriteLine("客户端:" + DateTime.Now);
                Console.WriteLine("--------------------");
            }
           
           
        }
        /// <summary>
        /// 读取客户端发送(即要发送给服务器)的消息
        /// </summary>
        /// <param name="o"></param>
        static void ReadText(object o)
        {
            NetworkStream netstream = o as NetworkStream;
            StreamReader sr = new StreamReader(netstream);
            while (true)
            {
                string con = sr.ReadLine();               
                Console.WriteLine(con);
                Console.WriteLine("服务端:" + DateTime.Now);
                Console.WriteLine("--------------------");
            }
        }
    }
}