激情五月天婷婷,亚洲愉拍一区二区三区,日韩视频一区,a√天堂中文官网8

<ul id="buwfs"><strike id="buwfs"><strong id="buwfs"></strong></strike></ul>
    <output id="buwfs"></output>
  • <dfn id="buwfs"><source id="buwfs"></source></dfn>
      <dfn id="buwfs"><td id="buwfs"></td></dfn>
      <div id="buwfs"><small id="buwfs"></small></div>
      <dfn id="buwfs"><source id="buwfs"></source></dfn>
      1. <dfn id="buwfs"><td id="buwfs"></td></dfn>
        始創(chuàng)于2000年 股票代碼:831685
        咨詢熱線:0371-60135900 注冊有禮 登錄
        • 掛牌上市企業(yè)
        • 60秒人工響應(yīng)
        • 99.99%連通率
        • 7*24h人工
        • 故障100倍補償
        全部產(chǎn)品
        您的位置: 網(wǎng)站首頁 > 幫助中心>文章內(nèi)容

        細說多線程(五) —— CLR線程池的I/O線程

        發(fā)布時間:  2012/9/16 6:35:56

        目錄

        一、線程的定義

        二、線程的基礎(chǔ)知識

        三、以ThreadStart方式實現(xiàn)多線程

        四、CLR線程池的工作者線程

        五、CLR線程池的I/O線程

        六、異步 SqlCommand

        七、并行編程與PLINQ

        八、計時器與鎖

         

        五、CLR線程池的I/O線程

        在前一節(jié)所介紹的線程都屬于CLR線程池的工作者線程,這一節(jié)開始為大家介紹一下CLR線程池的I/O線程

        I/O 線程是.NET專為訪問外部資源所設(shè)置的一種線程,因為訪問外部資源常常要受到外界因素的影響,為了防止讓主線程受影響而長期處于阻塞狀態(tài),.NET為多 個I/O操作都建立起了異步方法,例如:FileStream、TCP/IP、WebRequest、WebService等等,而且每個異步方法的使用 方式都非常類似,都是以BeginXXX為開始,以EndXXX結(jié)束,下面為大家一一解說。

         

        5.1  異步讀寫 FileStream

        需要在 FileStream 異步調(diào)用 I/O線程,必須使用以下構(gòu)造函數(shù)建立 FileStream 對象,并把useAsync設(shè)置為 true。

        FileStream stream = new FileStream ( string path, FileMode mode, FileAccess access, FileShare share, int bufferSize,bool useAsync ) ;

        其中 path 是文件的相對路徑或絕對路徑; mode 確定如何打開或創(chuàng)建文件; access 確定訪問文件的方式; share 確定文件如何進程共享; bufferSize 是代表緩沖區(qū)大小,一般默認最小值為8,在啟動異步讀取或?qū)懭霑r,文件大小一般大于緩沖大小; userAsync代表是否啟動異步I/O線程。

        注意:當(dāng)使用 BeginRead 和 BeginWrite 方法在執(zhí)行大量讀或?qū)憰r效果更好,但對于少量的讀/寫,這些方法速度可能比同步讀取還要慢,因為進行線程間的切換需要大量時間。

         

        5.1.1 異步寫入

        FileStream中包含BeginWrite、EndWrite 方法可以啟動I/O線程進行異步寫入。

        public override IAsyncResult BeginWrite ( byte[] array, int offset, int numBytes, AsyncCallback userCallback, Object stateObject )
        public override void EndWrite (IAsyncResult asyncResult )

         

        BeginWrite 返回值為IAsyncResult, 使用方式與委托的BeginInvoke方法相似,最好就是使用回調(diào)函數(shù),避免線程阻塞。在最后兩個參數(shù)中,參數(shù)AsyncCallback用于綁定回調(diào) 函數(shù); 參數(shù)Object用于傳遞外部數(shù)據(jù)。要注意一點:AsyncCallback所綁定的回調(diào)函數(shù)必須是帶單個 IAsyncResult 參數(shù)的無返回值方法。
        在例子中,把FileStream作為外部數(shù)據(jù)傳遞到回調(diào)函數(shù)當(dāng)中,然后在回調(diào)函數(shù)中利用IAsyncResult.AsyncState獲取FileStream對象,最后通過FileStream.EndWrite(IAsyncResult)結(jié)束寫入。

             class Program
             {
                 static void Main(string[] args)
                 {
                     //把線程池的最大值設(shè)置為1000
        ThreadPool.SetMaxThreads(1000, 1000); ThreadPoolMessage("Start"); //新立文件File.sour
        FileStream stream = new FileStream("File.sour", FileMode.OpenOrCreate, FileAccess.ReadWrite,FileShare.ReadWrite,1024,true); byte[] bytes = new byte[16384]; string message = "An operating-system ThreadId has no fixed relationship........"; bytes = Encoding.Unicode.GetBytes(message); //啟動異步寫入
        stream.BeginWrite(bytes, 0, (int)bytes.Length,new AsyncCallback(Callback),stream); stream.Flush(); Console.ReadKey(); } static void Callback(IAsyncResult result) { //顯示線程池現(xiàn)狀
        Thread.Sleep(200); ThreadPoolMessage("AsyncCallback"); //結(jié)束異步寫入
        FileStream stream = (FileStream)result.AsyncState; stream.EndWrite(result); stream.Close(); } //顯示線程池現(xiàn)狀
        static void ThreadPoolMessage(string data) { int a, b; ThreadPool.GetAvailableThreads(out a, out b); string message = string.Format("{0}\n CurrentThreadId is {1}\n "+ "WorkerThreads is:{2} CompletionPortThreads is :{3}", data, Thread.CurrentThread.ManagedThreadId, a.ToString(), b.ToString()); Console.WriteLine(message); } }

        由輸出結(jié)果可以看到,在使用FileStream.BeginWrite方法后,系統(tǒng)將自動啟動CLR線程池中I/O線程。


         

        5.1.2 異步讀取

        FileStream 中包含 BeginRead 與 EndRead 可以異步調(diào)用I/O線程進行讀取。

        public override IAsyncResult BeginRead ( byte[] array,int offset,int numBytes, AsyncCallback userCallback,Object stateObject)
        public override int EndRead(IAsyncResult asyncResult)

         

        其使用方式與BeginWrite和EndWrite相似,AsyncCallback用于綁定回調(diào)函數(shù); Object用于傳遞外部數(shù)據(jù)。在回調(diào)函數(shù)只需要使用IAsyncResut.AsyncState就可獲取外部數(shù)據(jù)。EndWrite 方法會返回從流讀取到的字節(jié)數(shù)量。

        首先定義 FileData 類,里面包含F(xiàn)ileStream對象,byte[] 數(shù)組和長度。然后把FileData對象作為外部數(shù)據(jù)傳到回調(diào)函數(shù),在回調(diào)函數(shù)中,把IAsyncResult.AsyncState強制轉(zhuǎn)換為 FileData,然后通過FileStream.EndRead(IAsyncResult)結(jié)束讀取。最后比較一下長度,若讀取到的長度與輸入的數(shù)據(jù) 長度不一至,則拋出異常。

         1      class Program
         2      {
         3          public class FileData
         4          {
         5              public FileStream Stream;
         6              public int Length;
         7              public byte[] ByteData;
         8          }
         9  
        10          static void Main(string[] args)
        11          {       
        12              //把線程池的最大值設(shè)置為1000
        13 ThreadPool.SetMaxThreads(1000, 1000); 14 ThreadPoolMessage("Start"); 15 ReadFile(); 16 17 Console.ReadKey(); 18 } 19 20 static void ReadFile() 21 { 22 byte[] byteData=new byte[80961024]; 23 FileStream stream = new FileStream("File1.sour", FileMode.OpenOrCreate, 24 FileAccess.ReadWrite, FileShare.ReadWrite, 1024, true); 25 26 //把FileStream對象,byte[]對象,長度等有關(guān)數(shù)據(jù)綁定到FileData對象中,以附帶屬性方式送到回調(diào)函數(shù)
        27 FileData fileData = new FileData(); 28 fileData.Stream = stream; 29 fileData.Length = (int)stream.Length; 30 fileData.ByteData = byteData; 31 32 //啟動異步讀取
        33 stream.BeginRead(byteData, 0, fileData.Length, new AsyncCallback(Completed), fileData); 34 } 35 36 static void Completed(IAsyncResult result) 37 { 38 ThreadPoolMessage("Completed"); 39 40 //把AsyncResult.AsyncState轉(zhuǎn)換為FileData對象,以FileStream.EndRead完成異步讀取
        41 FileData fileData = (FileData)result.AsyncState; 42 int length=fileData.Stream.EndRead(result); 43 fileData.Stream.Close(); 44 45 //如果讀取到的長度與輸入長度不一致,則拋出異常
        46 if (length != fileData.Length) 47 throw new Exception("Stream is not complete!"); 48 49 string data=Encoding.ASCII.GetString(fileData.ByteData, 0, fileData.Length); 50 Console.WriteLine(data.Substring(2,22)); 51 } 52 53 //顯示線程池現(xiàn)狀
        54 static void ThreadPoolMessage(string data) 55 { 56 int a, b; 57 ThreadPool.GetAvailableThreads(out a, out b); 58 string message = string.Format("{0}\n CurrentThreadId is {1}\n "+ 59 "WorkerThreads is:{2} CompletionPortThreads is :{3}", 60 data, Thread.CurrentThread.ManagedThreadId, a.ToString(), b.ToString()); 61 Console.WriteLine(message); 62 } 63 64 }

        由輸出結(jié)果可以看到,在使用FileStream.BeginRead方法后,系統(tǒng)將自動啟動CLR線程池中I/O線程。

         

        注意:如果你看到的測試結(jié)果正好相反:工作者線程為999,I/O線程為1000,這是因為FileStream的文件容量小于緩沖值1024所致的。此時文件將會一次性讀取或?qū)懭耄到y(tǒng)將啟動工作者線程而非I/O線程來處理回調(diào)函數(shù)。

         

         

        5.2 異步操作TCP/IP套接字

        在介紹 TCP/IP 套接字前先簡單介紹一下 NetworkStream 類,它是用于網(wǎng)絡(luò)訪問的基礎(chǔ)數(shù)據(jù)流。 NetworkStream 提供了好幾個方法控制套接字數(shù)據(jù)的發(fā)送與接收, 其中BeginRead、EndRead、BeginWrite、EndWrite 能夠?qū)崿F(xiàn)異步操作,而且異步線程是來自于CLR線程池的I/O線程。

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

        public override void WriteByte (byte value)
        public override void Write (byte[] buffer,int offset, int size)

        public override IAsyncResult BeginRead (byte [] buffer, int offset, int size,  AsyncCallback callback, Object state )
        public override int EndRead(IAsyncResult result)

        public override IAsyncResult BeginWrite (byte [] buffer, int offset, int size,  AsyncCallback callback, Object state )
        public override void EndWrite(IAsyncResult result)

         

        若要創(chuàng)建 NetworkStream,必須提供已連接的 Socket。而在.NET中使用TCP/IP套接字不需要直接與Socket打交道,因為.NET把Socket的大部分操作都放在 System.Net.TcpListener和System.Net.Sockets.TcpClient里面,這兩個類大大地簡化了Socket的操 作。一般套接字對象Socket包含一個Accept()方法,此方法能產(chǎn)生阻塞來等待客戶端的請求,而在TcpListener類里也包含了一個相似的 方法 public TcpClient AcceptTcpClient()用于等待客戶端的請求。此方法將會返回一個TcpClient 對象,通過 TcpClient 的 public NetworkStream GetStream()方法就能獲取NetworkStream對象,控制套接字數(shù)據(jù)的發(fā)送與接收。

         

        下面以一個例子說明異步調(diào)用TCP/IP套接字收發(fā)數(shù)據(jù)的過程。

        首先在服務(wù)器端建立默認地址127.0.0.1用于收發(fā)信息,使用此地址與端口500新建TcpListener對象,調(diào)用TcpListener.Start 偵聽傳入的連接請求,再使用一個死循環(huán)來監(jiān)聽信息。

        在ChatClient類包括有接收信息與發(fā)送信息兩個功能:當(dāng)接收到客戶端請求時,它會利 用 NetworkStream.BeginRead 讀取客戶端信息,并在回調(diào)函數(shù)ReceiveAsyncCallback中輸出信息內(nèi)容,若接收到的信息的大小小于1時,它將會拋出一個異常。當(dāng)信息成功 接收后,再使用 NetworkStream.BeginWrite 方法回饋信息到客戶端

             class Program
             {
                 static void Main(string[] args)
                 {
                     //設(shè)置CLR線程池最大線程數(shù)
        ThreadPool.SetMaxThreads(1000, 1000); //默認地址為127.0.0.1
        IPAddress ipAddress = IPAddress.Parse("127.0.0.1"); TcpListener tcpListener = new TcpListener(ipAddress, 500); tcpListener.Start(); //以一個死循環(huán)來實現(xiàn)監(jiān)聽
        while (true) { //調(diào)用一個ChatClient對象來實現(xiàn)監(jiān)聽
        ChatClient chatClient = new ChatClient(tcpListener.AcceptTcpClient()); } } } public class ChatClient { static TcpClient tcpClient; static byte[] byteMessage; static string clientEndPoint; public ChatClient(TcpClient tcpClient1) { tcpClient = tcpClient1; byteMessage = new byte[tcpClient.ReceiveBufferSize]; //顯示客戶端信息
        clientEndPoint = tcpClient.Client.RemoteEndPoint.ToString(); Console.WriteLine("Client's endpoint is " + clientEndPoint); //使用NetworkStream.BeginRead異步讀取信息
        NetworkStream networkStream = tcpClient.GetStream(); networkStream.BeginRead(byteMessage, 0, tcpClient.ReceiveBufferSize, new AsyncCallback(ReceiveAsyncCallback), null); } public void ReceiveAsyncCallback(IAsyncResult iAsyncResult) { //顯示CLR線程池狀態(tài)
        Thread.Sleep(100); ThreadPoolMessage("\nMessage is receiving"); //使用NetworkStream.EndRead結(jié)束異步讀取
        NetworkStream networkStreamRead = tcpClient.GetStream(); int length=networkStreamRead.EndRead(iAsyncResult); //如果接收到的數(shù)據(jù)長度少于1則拋出異常
        if (length < 1) { tcpClient.GetStream().Close(); throw new Exception("Disconnection!"); } //顯示接收信息
        string message = Encoding.UTF8.GetString(byteMessage, 0, length); Console.WriteLine("Message:" + message); //使用NetworkStream.BeginWrite異步發(fā)送信息
        byte[] sendMessage = Encoding.UTF8.GetBytes("Message is received!"); NetworkStream networkStreamWrite=tcpClient.GetStream(); networkStreamWrite.BeginWrite(sendMessage, 0, sendMessage.Length, new AsyncCallback(SendAsyncCallback), null); } //把信息轉(zhuǎn)換成二進制數(shù)據(jù),然后發(fā)送到客戶端
        public void SendAsyncCallback(IAsyncResult iAsyncResult) { //顯示CLR線程池狀態(tài)
        Thread.Sleep(100); ThreadPoolMessage("\nMessage is sending"); //使用NetworkStream.EndWrite結(jié)束異步發(fā)送
        tcpClient.GetStream().EndWrite(iAsyncResult); //重新監(jiān)聽
        tcpClient.GetStream().BeginRead(byteMessage, 0, tcpClient.ReceiveBufferSize, new AsyncCallback(ReceiveAsyncCallback), null); } //顯示線程池現(xiàn)狀
        static void ThreadPoolMessage(string data) { int a, b; ThreadPool.GetAvailableThreads(out a, out b); string message = string.Format("{0}\n CurrentThreadId is {1}\n " + "WorkerThreads is:{2} CompletionPortThreads is :{3}\n", data, Thread.CurrentThread.ManagedThreadId, a.ToString(), b.ToString()); Console.WriteLine(message); } }

        而在客戶端只是使用簡單的開發(fā)方式,利用TcpClient連接到服務(wù)器端,然后調(diào)用NetworkStream.Write方法發(fā)送信息,最后調(diào)用NetworkStream.Read方法讀取回饋信息

         1         static void Main(string[] args)
         2         {
         3             //連接服務(wù)端
        4 TcpClient tcpClient = new TcpClient("127.0.0.1", 500); 5 6 //發(fā)送信息
        7 NetworkStream networkStream = tcpClient.GetStream(); 8 byte[] sendMessage = Encoding.UTF8.GetBytes("Client request connection!"); 9 networkStream.Write(sendMessage, 0, sendMessage.Length); 10 networkStream.Flush(); 11 12 //接收信息
        13 byte[] receiveMessage=new byte[1024]; 14 int count=networkStream.Read(receiveMessage, 0,1024); 15 Console.WriteLine(Encoding.UTF8.GetString(receiveMessage)); 16 Console.ReadKey(); 17 }

        注意觀察運行結(jié)果,服務(wù)器端的異步操作線程都是來自于CLR線程池的I/O線程


         

        5.3 異步WebRequest

        System.Net.WebRequest 是 .NET 為實現(xiàn)訪問 Internet 的 “請求/響應(yīng)模型” 而開發(fā)的一個 abstract 基類, 它 主要有三個子類:FtpWebRequest、HttpWebRequest、FileWebRequest。當(dāng)使用 WebRequest.Create(string uri)創(chuàng)建對象時,應(yīng)用程序就可以根據(jù)請求協(xié)議判斷實現(xiàn)類來進行操作。FileWebRequest、FtpWebRequest、 HttpWebRequest 各有其作用:FileWebRequest 使用 “file://路徑” 的URI方式實現(xiàn)對本地資源和內(nèi)部文件的請求/響應(yīng)、FtpWebRequest 使用FTP文件傳輸協(xié)議實現(xiàn)文件請求/響應(yīng)、HttpWebRequest 用于處理HTTP的頁面請求/響應(yīng)。由于使用方法相類似,下面就以常用的HttpWebRequest為例子介紹一下異步WebRequest的使用方法。

        在使用ASP.NET開發(fā)網(wǎng)站的時候,往往會忽略了HttpWebRequest的使用,因為開發(fā) 都假設(shè)客戶端是使用瀏覽器等工具去閱讀頁面的。但如果你對REST開發(fā)方式有所了解,那對 HttpWebRequest 就應(yīng)該非常熟悉。它可以在路徑參數(shù)、頭文件、頁面主體、Cookie 等多處地方加入請求條件,然后對回復(fù)數(shù)據(jù)進行適當(dāng)處理。HttpWebRequest 包含有以下幾個常用方法用于處理請求/響應(yīng):

        public override Stream GetRequestStream ()
        public override WebResponse GetResponse ()

        public override IAsyncResult BeginGetRequestStream ( AsyncCallback callback, Object state )
        public override Stream EndGetRequestStream ( IAsyncResult asyncResult )
        public override IAsyncResult BeginGetResponse ( AsyncCallback callback, Object state )
        public override WebResponse EndGetResponse ( IAsyncResult asyncResult )

        其中BeginGetRequestStream、EndGetRequestStream 用于異步向HttpWebRequest對象寫入請求信息;  BeginGetResponse、EndGetResponse 用于異步發(fā)送頁面請求并獲取返回信息。使用異步方式操作Internet的“請求/響應(yīng)”,避免主線程長期處于等待狀態(tài),而操作期間異步線程是來自CLR 線程池的I/O線程。

        注意:請求與響應(yīng)不能使用同步與異步混合開發(fā)模式,即當(dāng)請求寫入使用GetRequestStream同步模式,即使響應(yīng)使用BeginGetResponse異步方法,操作也與GetRequestStream方法在于同一線程內(nèi)。

        下面以簡單的例子介紹一下異步請求的用法。

        首先為Person類加上可序列化特性,在服務(wù)器端建立Hanlder.ashx,通過Request.InputStream 獲取到請求數(shù)據(jù)并把數(shù)據(jù)轉(zhuǎn)化為String對象,此實例中數(shù)據(jù)是以 “Id:1” 的形式實現(xiàn)傳送的。然后根據(jù)Id查找對應(yīng)的Person對象,并把Person對象寫入Response.OutStream 中返還到客戶端。

        在客戶端先把 HttpWebRequird.Method 設(shè)置為 "post",使用異步方式通過BeginGetRequireStream獲取請求數(shù)據(jù)流,然后寫入請求數(shù)據(jù) “Id:1”。再使用異步方法BeginGetResponse 獲取回復(fù)數(shù)據(jù),最后把數(shù)據(jù)反序列化為Person對象顯示出來。

        注意:HttpWebRequire.Method默認為get,在寫入請求前必須把HttpWebRequire.Method設(shè)置為post,否則在使用BeginGetRequireStream 獲取請求數(shù)據(jù)流的時候,系統(tǒng)就會發(fā)出 “無法發(fā)送具有此謂詞類型的內(nèi)容正文" 的異常。

        Model

         namespace Model
         {
             [Serializable]
             public class Person
             {
                 public int ID
                 {
                     get;
                     set;
                 }
                 public string Name
                 {
                     get;
                     set;
                 }
                 public int Age
                 {
                     get;
                     set;
                 }
             }
         }


        服務(wù)器端

         1 public class Handler : IHttpHandler {
         2 
         3     public void ProcessRequest(HttpContext context)
         4     {
         5         //把信息轉(zhuǎn)換為String,找出輸入條件Id
        6 byte[] bytes=new byte[1024]; 7 int length=context.Request.InputStream.Read(bytes,0,1024); 8 string condition = Encoding.Default.GetString(bytes); 9 int id = int.Parse(condition.Split(new string[] { ":" }, 10 StringSplitOptions.RemoveEmptyEntries)[1]); 11 12 //根據(jù)Id查找對應(yīng)Person對象
        13 var person = GetPersonList().Where(x => x.ID == id).First(); 14 15 //所Person格式化為二進制數(shù)據(jù)寫入OutputStream
        16 BinaryFormatter formatter = new BinaryFormatter(); 17 formatter.Serialize(context.Response.OutputStream, person); 18 } 19 20 //模擬源數(shù)據(jù)
        21 private IList<Person> GetPersonList() 22 { 23 var personList = new List<Person>(); 24 25 var person1 = new Person(); 26 person1.ID = 1; 27 person1.Name = "Leslie"; 28 person1.Age = 30; 29 personList.Add(person1); 30 ........... 31 return personList; 32 } 33 34 public bool IsReusable 35 { 36 get { return true;} 37 } 38 }

        客戶端

             class Program
             {
                 static void Main(string[] args)
                 {
                     ThreadPool.SetMaxThreads(1000, 1000);
                     Request();
                     Console.ReadKey();
                 }
         
                 static void Request()
                 {
                     ThreadPoolMessage("Start"); 
                     //使用WebRequest.Create方法建立HttpWebRequest對象
        HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create( "http://localhost:5700/Handler.ashx"); webRequest.Method = "post"; //對寫入數(shù)據(jù)的RequestStream對象進行異步請求
        IAsyncResult result=webRequest.BeginGetRequestStream( new AsyncCallback(EndGetRequestStream),webRequest); } static void EndGetRequestStream(IAsyncResult result) { ThreadPoolMessage("RequestStream Complete"); //獲取RequestStream
        HttpWebRequest webRequest = (HttpWebRequest)result.AsyncState; Stream stream=webRequest.EndGetRequestStream(result); //寫入請求條件
        byte[] condition = Encoding.Default.GetBytes("Id:1"); stream.Write(condition, 0, condition.Length); //異步接收回傳信息
        IAsyncResult responseResult = webRequest.BeginGetResponse( new AsyncCallback(EndGetResponse), webRequest); } static void EndGetResponse(IAsyncResult result) { //顯出線程池現(xiàn)狀
        ThreadPoolMessage("GetResponse Complete"); //結(jié)束異步請求,獲取結(jié)果
        HttpWebRequest webRequest = (HttpWebRequest)result.AsyncState; WebResponse webResponse = webRequest.EndGetResponse(result); //把輸出結(jié)果轉(zhuǎn)化為Person對象
        Stream stream = webResponse.GetResponseStream(); BinaryFormatter formatter = new BinaryFormatter(); var person=(Person)formatter.Deserialize(stream); Console.WriteLine(string.Format("Person Id:{0} Name:{1} Age:{2}", person.ID, person.Name, person.Age)); } //顯示線程池現(xiàn)狀
        static void ThreadPoolMessage(string data) { int a, b; ThreadPool.GetAvailableThreads(out a, out b); string message = string.Format("{0}\n CurrentThreadId is {1}\n " + "WorkerThreads is:{2} CompletionPortThreads is :{3}\n", data, Thread.CurrentThread.ManagedThreadId, a.ToString(), b.ToString()); Console.WriteLine(message); } }

        從運行結(jié)果可以看到,BeginGetRequireStream、BeginGetResponse方法是使用CLR線程池的I/O線程。



        5.4 異步調(diào)用WebService

        相比TCP/IP套接字,在使用WebService的時候,服務(wù)器端需要更復(fù)雜的操作處理,使用時間往往會更長。為了避免客戶端長期處于等待狀態(tài),在配置服務(wù)引用時選擇 “生成異步操作”,系統(tǒng)可以自動建立異步調(diào)用的方式。

        以.NET 2.0以前,系統(tǒng)都是使用ASMX來設(shè)計WebService,而近年來WCF可說是火熱登場,下面就以WCF為例子簡單介紹一下異步調(diào)用WebService的例子。

        由于系統(tǒng)可以自動生成異步方法,使用起來非常簡單,首先在服務(wù)器端建立服務(wù) ExampleService,里面包含方法Method?蛻舳艘么朔⻊(wù)時,選擇 “生成異步操作”。然后使用 BeginMethod 啟動異步方法, 在回調(diào)函數(shù)中調(diào)用EndMethod結(jié)束異步調(diào)用。

        服務(wù)端

         1      [ServiceContract]
         2      public interface IExampleService
         3      {
         4          [OperationContract]
         5          string Method(string name);
         6      }
         7  
         8      public class ExampleService : IExampleService
         9      {
        10          public string Method(string name)
        11          {
        12              return "Hello " + name;
        13          }
        14      }
        15  
        16      class Program
        17      {
        18          static void Main(string[] args)
        19          {
        20              ServiceHost host = new ServiceHost(typeof(ExampleService));
        21              host.Open();
        22              Console.ReadKey();
        23              host.Close();
        24           }
        25      }
        26  
        27  <configuration>
        28      <system.serviceModel>
        29          <services>
        30              <service name="Example.ExampleService">
        31                  <endpoint address="" binding="wsHttpBinding" contract="Example.IExampleService">
        32                      <identity>
        33                          <dns value="localhost" />
        34                      </identity>
        35                  </endpoint>
        36                  <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        37                  <host>
        38                      <baseAddresses>
        39                          <add baseAddress="http://localhost:7200/Example/ExampleService/" />
        40                      </baseAddresses>
        41                  </host>
        42              </service>
        43          </services>
        44      </system.serviceModel>
        45  </configuration>

        客戶端

              class Program
              {
                  static void Main(string[] args)
                  {
                      //設(shè)置最大線程數(shù)
        ThreadPool.SetMaxThreads(1000, 1000); ThreadPoolMessage("Start"); //建立服務(wù)對象,異步調(diào)用服務(wù)方法
        ExampleServiceReference.ExampleServiceClient exampleService = new ExampleServiceReference.ExampleServiceClient(); exampleService.BeginMethod("Leslie",new AsyncCallback(AsyncCallbackMethod), exampleService); Console.ReadKey(); } static void AsyncCallbackMethod(IAsyncResult result) { Thread.Sleep(1000); ThreadPoolMessage("Complete"); ExampleServiceReference.ExampleServiceClient example = (ExampleServiceReference.ExampleServiceClient)result.AsyncState; string data=example.EndMethod(result); Console.WriteLine(data); } //顯示線程池現(xiàn)狀
        static void ThreadPoolMessage(string data) { int a, b; ThreadPool.GetAvailableThreads(out a, out b); string message = string.Format("{0}\n CurrentThreadId is {1}\n " + "WorkerThreads is:{2} CompletionPortThreads is :{3}\n", data, Thread.CurrentThread.ManagedThreadId, a.ToString(), b.ToString()); Console.WriteLine(message); } } <configuration> <system.serviceModel> <bindings> <wsHttpBinding> <binding name="WSHttpBinding_IExampleService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false"> <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" /> <security mode="Message"> <transport clientCredentialType="Windows" proxyCredentialType="None" realm="" /> <message clientCredentialType="Windows" negotiateServiceCredential="true" algorithmSuite="Default" /> </security> </binding> </wsHttpBinding> </bindings> <client> <endpoint address="http://localhost:7200/Example/ExampleService/" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IExampleService" contract="ExampleServiceReference.IExampleService" name="WSHttpBinding_IExampleService"> <identity> <dns value="localhost" /> </identity> </endpoint> </client> </system.serviceModel> </configuration>

        注意觀察運行結(jié)果,異步調(diào)用服務(wù)時,回調(diào)函數(shù)都是運行于CLR線程池的I/O線程當(dāng)中。
        億恩-天使(QQ:530997) 電話 037160135991 服務(wù)器租用,托管歡迎咨詢。


        本文出自:億恩科技【mszdt.com】

        服務(wù)器租用/服務(wù)器托管中國五強!虛擬主機域名注冊頂級提供商!15年品質(zhì)保障!--億恩科技[ENKJ.COM]

      2. 您可能在找
      3. 億恩北京公司:
      4. 經(jīng)營性ICP/ISP證:京B2-20150015
      5. 億恩鄭州公司:
      6. 經(jīng)營性ICP/ISP/IDC證:豫B1.B2-20060070
      7. 億恩南昌公司:
      8. 經(jīng)營性ICP/ISP證:贛B2-20080012
      9. 服務(wù)器/云主機 24小時售后服務(wù)電話:0371-60135900
      10. 虛擬主機/智能建站 24小時售后服務(wù)電話:0371-60135900
      11. 專注服務(wù)器托管17年
        掃掃關(guān)注-微信公眾號
        0371-60135900
        Copyright© 1999-2019 ENKJ All Rights Reserved 億恩科技 版權(quán)所有  地址:鄭州市高新區(qū)翠竹街1號總部企業(yè)基地億恩大廈  法律顧問:河南亞太人律師事務(wù)所郝建鋒、杜慧月律師   京公網(wǎng)安備41019702002023號
          0
         
         
         
         

        0371-60135900
        7*24小時客服服務(wù)熱線