程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C#.net同步異步SOCKET通訊和多線程總結

C#.net同步異步SOCKET通訊和多線程總結

編輯:關於C語言

同步套接字通信

Socket支持下的網上點對點的通信

服務端實現監聽連接,客戶端實現發送連接請求,建立連接後進行發送和接收數據的功能

服務器端建立一個socket,設置好本機的ip和監聽的端口與socket進行綁定,開始監聽連接請求,當接收到連接請求後,發送確認,同客戶端建立連接,開始與客戶端進行通信。

客戶端建立一個socket,設置好服務器端的IP和提供服務的端口,發出連接請求,接收到服務的確認後,盡力連接,開始與服務器進行通信。

服務器端和客戶端的連接及它們之間的數據傳送均采用同步方式。

 

Socket

Socket是tcp\ip網絡協議接口。內部定義了許多的函數和例程。可以看成是網絡通信的一個端點。在網絡通信中需要兩個主機或兩個進程。通過網絡傳遞數據,程序在網絡對話的每一端需要一個socket。

       Tcp/IP傳輸層使用協議端口將數據傳送給一個主機的特定應用程序,協議端口是一個應用程序的進程地址。傳輸層模塊的網絡軟件模塊要於另一個程序通信,它將使用協議端口,socket是運行在傳輸層的api,使用socket建立連接發送數據要指定一個端口給它。

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解析地址的尋址方案。InterNetwork標示需要ip版本4的地址,InterNetworkV6需要ip版本6的地址

SocketType參數指定socket類型Raw支持基礎傳輸協議訪問,Stream支持可靠,雙向,基於連接的數據流。

ProtocolType表示socket支持的網絡協議

 

定義主機對象:

IPEndPoint類:IPEndPoint構造方法  位置:System.Net

原型:1)   public IPEndPoint(IPAddress address,int port)     2)public IPEndPoint(long address,int port) 參數1整型int64如123456,參數2端口int32

主機解析:

利用DNS服務器解析主機,使用Dns.Resolve方法

原型:public static IPHostEntry Resolve(string hostname) 參數:待解析的主機名稱,返回IPHostEntry類值,IPHostEntry為Internet主機地址信息提供容器,該容器提供存有IP地址列表,主機名稱等。

Dns.GetHostByName獲取本地主機名稱

原型:public static IPHostEntry GetHostByName(string hostname)

GetHostByAddress

原型:1)public static IPHostEntry GetHostByAddress(IPAddress address) 參數:IP地址 2)public static IPHostEntry GetHostByAddress(string address) IP地址格式化字符串

 

端口綁定和監聽:

同步套接字服務器主機的綁定和端口監聽

Socket類的Bind(綁定主機),Listen(監聽端口),Accept(接收客戶端的連接請求)

Bind:原型:public void Bind(EndPoint LocalEP)參數為主機對象 IPEndPoint

Listen:原型:public void Listen(int backlog) 參數整型數值,掛起隊列最大值

accept:原型:public socket accept() 返回為套接字對象

演示程序:

IPAddress myip=IPAddress.Parse(“127.0.0.1”);

IPEndPoint myserver=new IPEndPoint(myip,2020);

Socket sock=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);

Sock.Bind(myserver);

Sock.Listen(50);

Socket bbb=sock.Accept();

發送數據:方法1:socket類的send方法二:NetworkStream類Write

send原型:public int Send(byte[] buffer) 字節數組 

public int Send(byte[],SocketFlags)原型2說明,SocketFlags成員列表:DontRoute(不使用路由表發送),MaxIOVectorLength(為發送和接收數據的wsabuf結構數量提供標准值)None 不對次調用使用標志) OutOfBand(消息的部分發送或接收)Partial(消息的部分發送或接收) Peek(查看傳入的消息)

原型三:public int Send(byte[],int,SocketFlags) 參數二要發送的字節數

原型四:public int Send(byte[],int,int,SocketFlags) 參數二為Byte[]中開始發送的位置

演示:

Socket bbb=sock.Accept();

Byte[] bytes=new Byte[64];

string send="aaaaaaaaaaaa";

bytes=System.Text.Encoding.BigEndianUnicode.GetBytes(send.ToCharArray());

bbb.Send(bytes,bytes.length,0);//將byte數組全部發送

NetWordStream類的Write方法發送數據

原型:public override void write(byte[] buffer,int offset,int size) 字節數組,開始字節位置,總字節數

 

Socket bbb=sock.Accept();

NetWorkStream stre=new NewWorkStream(bbb);

Byte[] ccc=new Byte[512];

string sendmessage="aaaaaaaaaaaaaa";

ccc=System.Text.Encoding.BigEndianUnicode.GetBytes(sendmessage);

stre.Write(ccc,0,ccc.length);

接收數據:Socket類Receive或NetworkStream類Read

Socket類Receive方法

原型:public int Receive(byte[] buffer)   

2)public int Receive(byte[],SocketFlags)

3)public int Receive(byte[],int,SocketFlags)   

4)public int Receive(byte[],int,int,SocketFlags)

.....

Socket bbb=sock.Accept();

........

Byte[] ccc=new Byte[512];

bbb.Receive(ccc,ccc.Length,0);

string rece=System.Text.Encoding.BigEndianUnicode.GetString(ccc);

richTextBox1.AppendText(rece+"\r\n");

 

NetworkStream類的Read方法接收數據

public override int Read(int byte[] buffer,int offset,int size)

 

演示:bbb=sock.Accept();

.......

NetworkStream stre=new NetworkStream(bbb);

Byte[] ccc=new Byte[512];

stre.Read(ccc,0,ccc.Length);

string readMessage=System.Text.Encoding.BigEndianUnicode.GetString(ccc);

線程

線程創建:System.Threading空間下的Thread類的構造方法:

原型:public Thread(ThreadStart start) ThreadStart類型值     

       Thread thread=new Thread(new ThreadStart(accp));

       Private void accp(){}//使用線程操作

線程啟動

Thread thread=new Thread(new ThreadStart(accp));

線程暫停與重新啟動

啟動線程使用Thread.Sleep是當前線程阻塞一段時間Thread.Sleep(Timeout.Infinite)是線程休眠,直到被調用Thread.Interrrupt的另一個線程中斷或被Thread.Abort中止。

一個線程不能對另一個調用Sleep,可以使用Thread.Suspend來暫停線程,當線程對自身調用Thread.Suspend將阻塞,直到該線程被另一個線程繼續,當一個線程對另一個調用,該調用就成為使另一個線程暫停的非阻塞調用。調用Thread.Resume使另一個線程跳出掛起狀態並使該線程繼續執行,而與調用Thread.Suspend的次數無關

線程休眠:Thread.Sleep(10000);

線程掛起:Thread thread=new Thread(new ThreadStart(accp));

                Thread.start();

                Thread.Suspend();

重新啟動:Thread thread=new Thread(new ThreadStart(accp));

               Thread.start();

               Thread.Suspend();

               Thread.Resume();

阻塞線程的方法:thread.Join使用一個線程等待另一個線程停止

Thread.Join

Public void Join();

Public void Join(int millisecondsTimeout);毫秒

Public bool Join(TimeSpan timeout);時間間隔類型值

實例:Thread thread=new Thread(new ThreadStart(accp));

              Thread.start();

              Thread.Join(10000);

線程銷毀:

Thread.Abort,Thread.Interrupt

Abort方法引發ThreadAbortException,開始中止此線程的過程,是一個可以由應用程序代碼捕獲的特殊異常,ResetAbort可以取消Abort請求,可以組織ThreadAbortException終止此線程,線程不一定會立即終止,根本不終止。

對尚未啟動的線程調用Abort,則當調用Start時該線程將終止。對已經掛起的線程調用Abort,則該線程將繼續,然後終止。對阻塞或正在休眠的線程調用Abort,則該線程被中斷,然後終止。

Thread類的Abort方法:

Public void Abort()

Public void Abort(object stateinfo);

演示:

Thread thread=new Thread(new ThreadStart(accp));

Thread.Start();

Thread.Abort();

Thread.Join(10000);

 

Socket編程原理:

Unix的i/o命令集,模式為開-讀/寫-關 open write/read close

用戶進程進行i/o操作

用戶進程調用打開命令,獲取文件或設備的使用權,並返回描述文件或設備的整數,以描述用戶打開的進程,該進程進行讀寫操作,傳輸數據,操作完成,進程關閉,通知os對哪個對象進行了使用。

Unix網絡應用編程:BSD的套接字socket,unix的System V 的TLI。

套接字編程的基本概念:

網間進程通信:源於單機系統,每個進程在自己的地址范圍內進行運行,保證互相不干擾且協調工作。操作系統為進程之間的通信提供設施:

Unix BSD 管道pipe,命名管道named pipe軟中斷信號signal

Unix System V 消息message 共享存儲區 shared memory 信號量semaphore

以上僅限於本機進程之間通信。

端口:網絡上可以被命名和尋址的通信端口,是操作系統可以分配的一種資源,網絡通信的最終地址不是主機地址,是可以描述進程的摸中標識符。TCP/IP提出協議端口porotocol port端口,表示通信進程。

       進程通過os調用綁定連接端口,而在傳輸層傳輸給該端口的數據傳入進程中處理,同樣在進程的數據需要傳給傳輸層也是通過綁定端口實現。進程對端口的操作相當於對os中的i/o文件進行操作,每一個端口也對應著一個端口號,tcp/ip協議分為tcp和udp,雖然有相同port number的端口,但是互相也不沖突。 端口號的分配有全局分配,本地分配(動態分配),當進程需要訪問傳輸層,os分配給進程一個端口號。全局分配,就是os固定分配的端口,標准的服務器都有固定的全局公認的端口號提供給服務。小於256的可以作為保留端口。

       地址:網絡通信中的兩台機器,可以不再同一個網絡,可能間隔(網關,網橋,路由器等),所以可以分為三層尋址

機器在不同的網絡則有該網絡的特定id

同一個網絡中的機器應該有唯一的機器id

一台機器內的進程應該有自己的唯一id

通常主機地址=網絡ID+主機ID  tcp/ip中使用16位端口號來表示進程。

網絡字節順序,高價先存,tcp和udp都使用16或32整數位的高價存儲,在協議的頭文件中。

半相關:在網絡中一個進程為協議+本地地址+端口號=三元組,也叫半相關,表示半部分。

全相關:兩台機器之間通信需要使用相同協議

              協議+本地地址+本地端口號+遠程地址+遠程端口號 五元組 全相關。

順序:兩個連續的報文在網絡中可能不會通過相同的路徑到達,所以接收的順序會和發送的順序不一致。順序是接收順序與發送順序一致。Tcp/ip提供該功能。

差錯控制:檢查數據差錯:檢查和CheckSum機制 檢查連接差錯:雙方確認應答機制。

流控制:雙方傳輸數據過程中,保證數據傳輸速率的機制,保證數據不丟失。

字節流:把傳輸中的報文當作一個字節序列,不提供任何數據邊界。

全雙工/半雙工:兩個方向發送或一個方向發送

緩存/帶外數據:字節流服務中,沒有報文邊界,可以同一時刻讀取任意長度的數據。為保證傳輸正確或流協議控制,需要使用緩存,交互型的應用程序禁用緩存。

數據傳送中,希望不通過常規傳輸方式傳送給用戶以便及時處理的某一類信息(unix系統的中斷鍵delete,Control-c)、終端流控制符Control-s、Control-q)為帶外數據。

客戶/服務器模式主動請求方式:

1.       打開通信通道,通知本地主機,在某一個公認地址上接收客戶請求

2.       等待客戶請求到達端口

3.       接收到重復服務請求,處理請求發送應答信號。接收到並發服務請求。要激活一個新進程處理客戶請求,unix系統fork、exec,新進程處理客戶請求,不需要對其他請求作出應答,服務完成後,關閉此進程與客戶的通信鏈路。終止

4.       返回第二步,等待另一個客戶請求。

5.       關閉服務端

客戶方:

1.       打開一通信通道,並連接到服務器所在主機的特定端口。

2.       向服務器發送服務請求報文,等待並接收應答;繼續提出請求…….

3.       請求結束以後關閉通信通道並終止。

1.       客戶與服務器進程的作用非對稱,編碼不同

2.       服務進程先於客戶請求而啟動,系統運行,服務進程一致存在,直到正常退出或強迫退出

套接字類型:

TCP/IP的socket

Sock_stream可靠的面對連接數據傳輸,無差錯、無重復發送,安照順序發送接收,內設流量控制,避免數據流超限,數據為字節流,無長度限制,FTP流套接字。

Sock_DGRAM 無連接的服務,數據包以獨立包的形式發送,不提供無措保證,數據可能丟失重復,發送接收的順序混亂,網絡文件系統nfs使用數據報式套接字。

Sock_Ram 接口允許較底層協議,IP,ICMP直接訪問,檢查新的協議實現或訪問現有服務中配置的新設備。

服務端:

using System.Net;

using System.Net.Sockets;

using System.Text;

using System.Threading;

Thread mythread ;

Socket socket;

// 清理所有正在使用的資源。

        protected override void Dispose( bool disposing )

         {

              try

             {

            socket.Close();//釋放資源

            mythread.Abort ( ) ;//中止線程

             }

             catch{ }

             if( disposing )

              {

                   if (components != null)

                   {

                       components.Dispose();

                   }

              }

              base.Dispose( disposing );

         }       

         public static IPAddress GetServerIP()

         {

              IPHostEntry IEh=Dns.GetHostByName(Dns.GetHostName());

              return IEh.AddressList[0];

         }

         private void BeginListen()

         {

              IPAddress ServerIp=GetServerIP();

              IPEndPoint IEp=new IPEndPoint(ServerIp,8000);

              socket=new

                       Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);

              byte[] byteMessage=new byte[100]; 

              this.label1.Text=IEp.ToString();

              socket.Bind(IEp); 

//            do

              while(true)

              {

                   try

                   {

                       socket.Listen(5);

                       Socket newSocket=socket.Accept();

                       newSocket.Receive(byteMessage);

                       string sTime = DateTime.Now.ToShortTimeString ( ) ;

string msg=sTime+":"+"Message from:";

msg+=newSocket.RemoteEndPoint.ToString()+Encoding.Default.GetString(byteMessage);

                       this.listBox1.Items.Add(msg);

                   }

                   catch(SocketException ex)

                   {

                       this.label1.Text+=ex.ToString();

                   }

              }

//            while(byteMessage!=null);

         }

         //開始監聽

         private void button1_Click(object sender, System.EventArgs e)

         {

              try

              {

                   mythread = new Thread(new ThreadStart(BeginListen));

                   mythread.Start();

              }

              catch(System.Exception er)

              {

                   MessageBox.Show(er.Message,"完成",MessageBoxButtons.OK,MessageBoxIcon.Stop);

              }

         }

客戶端:

using System.Net;

using System.Net.Sockets;

using System.Text;

         private void button1_Click(object sender, System.EventArgs e)

         {

              BeginSend();      

         }

         private void BeginSend()

         {            

              string ip=this.txtip.Text;

              string port=this.txtport.Text;

              IPAddress serverIp=IPAddress.Parse(ip);           

              int serverPort=Convert.ToInt32(port);

              IPEndPoint IEp=new IPEndPoint(serverIp,serverPort); 

              byte[] byteMessage; 

//            do

//            {

                   Socket socket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);

                   socket.Connect(IEp);

                   byteMessage=Encoding.ASCII.GetBytes(textBox1.Text);

                   socket.Send(byteMessage);

                   socket.Shutdown(SocketShutdown.Both);

                   socket.Close();

//            }

//            while(byteMessage!=null);

         }

基於TCP協議的發送和接收端

TCP協議的接收端

using System.Net.Sockets ; //使用到TcpListen類

using System.Threading ; //使用到線程 

using System.IO ; //使用到StreamReader類

         int port = 8000; //定義偵聽端口號

         private Thread thThreadRead; //創建線程,用以偵聽端口號,接收信息

         private TcpListener tlTcpListen; //偵聽端口號

         private bool blistener = true; //設定標示位,判斷偵聽狀態

         private NetworkStream nsStream; //創建接收的基本數據流 

         private StreamReader srRead;

         private System.Windows.Forms.StatusBar statusBar1;

         private System.Windows.Forms.Button button1;

         private System.Windows.Forms.ListBox listBox1; //從網絡基礎數據流中讀取數據

         private TcpClient tcClIEnt ;

          private void Listen ( )

         {

              try

              {

                   tlTcpListen = new TcpListener ( port ) ; //以8000端口號來初始化TcpListener實例

                   tlTcpListen.Start ( ) ; //開始監聽

                   statusBar1.Text = "正在監聽..." ;

                   tcClient = tlTcpListen.AcceptTcpClIEnt ( ) ; //通過TCP連接請求

                   nsStream = tcClIEnt.GetStream ( ) ; //獲取用以發送、接收數據的網絡基礎數據流

                   srRead=new StreamReader(nsStream);//以得到的網絡基礎數據流來初始化StreamReader實例

 

                   statusBar1.Text = "已經連接!";

 

                    while( blistener ) //循環偵聽

                   {

                       string sMessage = srRead.ReadLine();//從網絡基礎數據流中讀取一行數據

                       if ( sMessage == "STOP" ) //判斷是否為斷開TCP連接控制碼

                       {

                            tlTcpListen.Stop(); //關閉偵聽

                            nsStream.Close(); //釋放資源

                            srRead.Close();

                            statusBar1.Text = "連接已經關閉!" ;

                            thThreadRead.Abort(); //中止線程

                            return;

                       }

                       string sTime = DateTime.Now.ToShortTimeString ( ) ; //獲取接收數據時的時間

                       listBox1.Items.Add ( sTime + " " + sMessage ) ;

                   }

              }

              catch ( System.Security.SecurityException )

              {

                   MessageBox.Show ( "偵聽失敗!" , "錯誤" ) ;

              }

         }

         //開始監聽

         private void button1_Click(object sender, System.EventArgs e)

         {

              thThreadRead = new Thread ( new ThreadStart ( Listen ) );

              thThreadRead.Start();//啟動線程          

              button1.Enabled=false;

         }

         // 清理所有正在使用的資源。

         protected override void Dispose( bool disposing )

         {

              try

              {

                   tlTcpListen.Stop(); //關閉偵聽

                   nsStream.Close();

                   srRead.Close();//釋放資源

                   thThreadRead.Abort();//中止線程

              }

              catch{}

              if( disposing )

              {

                   if (components != null)

                   {

                       components.Dispose();

                   }

             }

              base.Dispose( disposing );

         }

TCP協議的發送端

using System.Net.Sockets; //使用到TcpListen類

using System.Threading; //使用到線程

using System.IO; //使用到StreamWriter類

using System.Net; //使用IPAddress類、IPHostEntry類等

          private StreamWriter swWriter; //用以向網絡基礎數據流傳送數據 

         private NetworkStream nsStream; //創建發送數據的網絡基礎數據流 

         private TcpClient tcpClIEnt;

         private System.Windows.Forms.Button button1;

         private System.Windows.Forms.TextBox textBox1;

         private System.Windows.Forms.Button button2;

         private System.Windows.Forms.TextBox textBox2;

         private System.Windows.Forms.StatusBar statusBar1;

         private System.Windows.Forms.Label label1;

         private System.Windows.Forms.Label label2; //通過它實現向遠程主機提出TCP連接申請 

         private bool tcpConnect = false; //定義標識符,用以表示TCP連接是否建立

          //連接 

         private void button1_Click(object sender, System.EventArgs e)

         {

              IPAddress ipRemote ;

              try

              {

                   ipRemote = IPAddress.Parse ( textBox1.Text ) ;

              }

              catch //判斷給定的IP地址的合法性

              {

                   MessageBox.Show ( "輸入的IP地址不合法!" , "錯誤提示!" ) ;

                   return ;

              }

              IPHostEntry ipHost ;

              try

              {

                   ipHost = Dns.Resolve ( textBox1.Text ) ; 

              }

              catch //判斷IP地址對應主機是否在線

              {

 

                   MessageBox.Show ("遠程主機不在線!" , "錯誤提示!" ) ;

                   return ;

              }

              string sHostName = ipHost.HostName ;

              try

              {

                   TcpClient tcpClient = new TcpClIEnt(sHostName,8000);//對遠程主機的8000端口提出TCP連接申請

                   nsStream = tcpClIEnt.GetStream();//通過申請,並獲取傳送數據的網絡基礎數據流  

                   swWriter = new StreamWriter(nsStream);//使用獲取的網絡基礎數據流來初始化StreamWriter實例

                   button1.Enabled = false ;

                   button2.Enabled = true ;

                   tcpConnect = true ;

                   statusBar1.Text = "已經連接!" ;

              }

              catch

              {

                   MessageBox.Show ( "無法和遠程主機8000端口建立連接!" , "錯誤提示!" ) ;

                   return ;

              }

         }

          //發送

         private void button2_Click(object sender, System.EventArgs e)

         {

              if (textBox2.Text !="")

              {

                   swWriter.WriteLine(textBox2.Text);//刷新當前數據流中的數據

                   swWriter.Flush();

              }

              else

              {

                   MessageBox.Show("發送信息不能為空!","錯誤提示!");

              }

         }

         // 清理所有正在使用的資源。

         protected override void Dispose( bool disposing )

         {

              if ( tcpConnect )

              {

                   swWriter.WriteLine ( "STOP" ) ; //發送控制碼  

                   swWriter.Flush (); //刷新當前數據流中的數據  

                   nsStream.Close (); //清除資源

                   swWriter.Close ();

              }

              if( disposing )

              {

                   if (components != null)

                   {

                       components.Dispose();

                   }

              }

              base.Dispose( disposing );

         }

異步套接字

BeginAccept

Public IAsyncResult BeginAccept{AsyncCallback callback,object state}

AsyncCallback異步回調方法 object state自定義對象, 返回IasyncResult

Using System;

Namespace mySocket

{

       Public class  Stateobject

{

       Public StateObject(){構造函數邏輯}

}

}à>

Using System;

Using System.Net;

Using System.Net.Sockets;

Using System.Threading;

Using System.Text;

Namespace mysocket

{

       Public Class StateObject

{

       Public Socket worksocket=null;

       Public const int buffersize=1024;

       Public byte[] buffer=new byte[buffersize];

       Public StringBuilder sb=new StringBuilder();

       Public StateObject()

       {}

}

}

實現主機綁定和端口監聽:

Private IPAddress myIP=IPAddress.Parse(“127.0.0.1”);

Private IPEndPoint MyServer;

Private Socket mySocket;

Private Socket Handler;

Private Static ManualResetEvent myreset =new ManualResetEvent(false);

Try

{

       IPHostEntry myhost=new IPHostEntry();

       Myhost=dns.gethostbyName(“”);

       String IPString =myhost.Addresslist[0].tostring();

       Myip=IPAddress.Parse(IPString);

}

Catch{MessageBox.Show(“您輸入的IP地址格式不正確,重新輸入!”);}

Try

{

       MyServer=new IPEndPoint(myIP,Int32.Parse(“Port”));

       Mysocket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,Protocol.Tcp);

       Mysocket.Bind(Myserver);

       Mysocket.Listen(50);

       Thread thread=new Thread(new ThreadStart(target));

       Thread.Start();

}

Catch(Exception ee){}

線程target

Private void target()

{

       While(true)

{

       myReset.Reset();

       mysocket.BeginAccept(new AsyncCallBack(AcceptCallback),mysocket);

       myReset.WaitOne();

}

}

異步回調方法AcceptCallBack

Private void AcceptCallback(IAsyncResault ar)

{

       myReset.Set();

       Socket Listener=(Socket)ar.AsyncState;

       Handler=Listener.EndAccept(ar);

       StateObject state=new StateObject();

       State.workSocket=handler;

       Try

       {

       Byte[] byteData=System.Text.Encoding.BigEndianUnicode.GetBytes(“通話!”+”\n\r”);

    Handler.BeginSend(byuteData,0,byteData.Length,0,new AsyncCallback(SendCallback),handler);

}

Catch(Exception ee)

{MessageBox.Show(ee.Message);}

Thread thread=new Thread(new ThreadStart(begreceive));

Thread.Start();

}

 

多線程:

每個窗體自己都在不同的線程上面運行,如果需要在窗體之間交互,需要在線程之間交互

當線程sleep,系統就使之退出執行隊列,當睡眠結束,系統產生時鐘中斷,使該線程回到執行隊列中,回復線程的執行。

如果父線程先於子線程結束,那麼子線程在父線程結束的時候被迫結束,Thread.Join()是父線程等待子線程結束。Abort帶來的是不可回復的終止線程

起始線程為主線程,前台線程全部結束,則主線程可以終止,後台線程無條件終止。

前台線程不妨礙程序終止,一旦進程的所有前台線程終止,則clr調用任意一個還存活的後台線程的abort來徹底終止進程。

掛起,睡眠(阻塞,暫停)

Thread.Suspend不會使線程立即停止執行,直到線程到達安全點的時候它才可以將該線程掛起,如果線程尚未運行或這已經停止,則不能被掛起,調用thread.resume使另一個線程跳出掛起狀態,繼續執行。

一個線程不能對另一個線程調用sleep,但是可以suspend。

Lock可以把一段代碼定義為互斥段critical section 互斥段在一個時刻內只允許一個線程進入執行,其他線程必須等待

多線程公用對象,不應該使用lock,monitor提供了線程共享資源的方案,monitor可以鎖定一個對象,線程只有得到鎖才可以對該對象進行操作

一個進程開始至少有一個主線程。系統加載程序時創建主執行線程

消息隊列與線程相關

一開始創建線程就產生消息隊列了,一個線程可以創建多個窗體,而發給這些窗體的消息都同意發送到同一個消息隊列中了,消息結構中有msg.hwnd指出該條消息與哪個窗體相關

DispatchMessage()函數依照這個保證消息分派處理自動化而且不會出錯。

線程控制方法:

Start線程開始運行

Sleep 是線程暫停一段指定時間

Suspend 線程在到達安全點後暫停

Abort 線程到達安全點後停止

Resume 重新啟動掛起的線程

Join 當前線程等待其他線程運行結束。如果使用超時值,且線程在分配的時間內結束,方法返回true

安全點:代碼中的某些位置,這些位置公共語言運行時可以安全的執行自動垃圾回收,即釋放未使用的變量並回收內存,調用線程的abort和suspend方法時,公共語言運行時將分析代碼並確定線程停止運行的適當位置。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved