C#線程處置系列之線程池中的I/O線程。本站提示廣大學習愛好者:(C#線程處置系列之線程池中的I/O線程)文章只能為提供參考,不一定能成為您想要的結果。以下是C#線程處置系列之線程池中的I/O線程正文
1、I/O線程完成對文件的異步
1.1 I/O線程引見:
關於線程所履行的義務來講,可以把線程分為兩品種型:任務者線程和I/O線程。
任務者線程用來完成一些盤算的義務,在義務履行的進程中,須要CPU不連續地處置,所以,在任務者線程的履行進程中,CPU和線程的資本是充足應用的。
I/O線程重要用來完成輸出和輸入的任務的,在這類情形下, 盤算機須要I/O裝備完成輸出和輸入的義務,在處置進程中,CPU是不須要介入處置進程的,此時正在運轉的線程將處於期待狀況,只要等義務完成後才會有事可做, 如許就形成線程資本糟蹋的成績。為懂得決如許的成績,可以經由過程線程池來處理如許的成績,讓線程池來治理線程,後面曾經引見過線程池了, 在這裡就不講了。
關於I/O線程,我們可以將輸出輸入操作分紅三個步調:啟動、現實輸出輸入、處置成果。用於現實輸出輸入可由硬件完成,其實不須要CPU的介入,而啟動和處置成果也能夠不在統一個線程上,如許便可以充足應用線程資本。在.Net中經由過程以Begin開首的辦法來完成啟動,以End開首的辦法來處置成果,這兩個辦法可以運轉在分歧的線程,如許我們就完成了異步編程了。
1.2 .Net中若何應用異步
留意:
其實當我們挪用Begin開首的辦法就是將一個I/O線程排入到線程池中(挪用Begin開首的辦法就把I/O線程參加到線程池中治理都是.Net機制幫我們完成的)。
(由於有些人會問甚麼處所用到了線程池了,任務者線程由線程池治理很悅目出來,由於創立任務者線程直接挪用ThreadPool.QueueUserWorkItem辦法來把任務者線程排入到線程池中)。
在.net Framework中的FCL中有很多類型可以或許對異步操作供給支撐,個中在FileStream類中就供給了對文件的異步操作的辦法。
FileStream類要挪用I/O線程要完成異步操作,起首要樹立一個FileStream對象。
經由過程上面的結構函數來初始化FileStream對象完成異步操作(異步讀取和異步寫入):
public FileStream (string path, FileMode mode, FileAccess access, FileShare share,int bufferSize,bool useAsync)
個中path代表文件的絕對途徑或相對途徑,mode代表若何翻開或創立文件,access代表拜訪文件的方法,share代表文件若何由過程同享,buffersize代表緩沖區的年夜小,useAsync代表應用異步I/O照樣同步I/O,設置為true時,解釋應用異步I/O.
上面經由過程代碼來進修下異步寫入文件:
using System; using System.IO; using System.Text; using System.Threading; namespace AsyncFile { class Program { static void Main(string[] args) { const int maxsize = 100000; ThreadPool.SetMaxThreads(1000,1000); PrintMessage("Main Thread start"); // 初始化FileStream對象 FileStream filestream = new FileStream("test.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite, 100, true); //打印文件流翻開的方法 Console.WriteLine("filestream is {0} opened Asynchronously", filestream.IsAsync ? "" : "not"); byte[] writebytes =new byte[maxsize]; string writemessage = "An operation Use asynchronous method to write message......................."; writebytes = Encoding.Unicode.GetBytes(writemessage); Console.WriteLine("message size is: {0} byte\n", writebytes.Length); // 挪用異步寫入辦法比信息寫入到文件中 filestream.BeginWrite(writebytes, 0, writebytes.Length, new AsyncCallback(EndWriteCallback), filestream); filestream.Flush(); Console.Read(); } // 當把數據寫入文件完成後挪用此辦法來停止異步寫操作 private static void EndWriteCallback(IAsyncResult asyncResult) { Thread.Sleep(500); PrintMessage("Asynchronous Method start"); FileStream filestream = asyncResult.AsyncState as FileStream; // 停止異步寫入數據 filestream.EndWrite(asyncResult); filestream.Close(); } // 打印線程池信息 private static void PrintMessage(String data) { int workthreadnumber; int iothreadnumber; // 取得線程池中可用的線程,把取得的可用任務者線程數目賦給workthreadnumber變量 // 取得的可用I/O線程數目給iothreadnumber變量 ThreadPool.GetAvailableThreads(out workthreadnumber, out iothreadnumber); Console.WriteLine("{0}\n CurrentThreadId is {1}\n CurrentThread is background :{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is: {4}\n", data, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsBackground.ToString(), workthreadnumber.ToString(), iothreadnumber.ToString()); } } }
運轉成果:
從運轉成果可以看出,此時是挪用線程池中的I/O線程去履行回調函數的,同時在工程所的的bin\Debug文件目次下有生成一個text.txt文件,翻開文件可以曉得外面的內容恰是你寫入的。
上面演示若何從適才的文件中異步讀取我們寫入的內容:
using System; using System.IO; using System.Text; using System.Threading; namespace AsyncFileRead { class Program { const int maxsize = 1024; static byte[] readbytes = new byte[maxsize]; static void Main(string[] args) { ThreadPool.SetMaxThreads(1000, 1000); PrintMessage("Main Thread start"); // 初始化FileStream對象 FileStream filestream = new FileStream("test.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite, 100, false); // 異步讀取文件內容 filestream.BeginRead(readbytes, 0, readbytes.Length, new AsyncCallback(EndReadCallback), filestream); Console.Read(); } private static void EndReadCallback(IAsyncResult asyncResult) { Thread.Sleep(1000); PrintMessage("Asynchronous Method start"); // 把AsyncResult.AsyncState轉換為State對象 FileStream readstream = (FileStream)asyncResult.AsyncState; int readlength = readstream.EndRead(asyncResult); if (readlength <=0) { Console.WriteLine("Read error"); return; } string readmessage = Encoding.Unicode.GetString(readbytes, 0, readlength); Console.WriteLine("Read Message is :" + readmessage); readstream.Close(); } // 打印線程池信息 private static void PrintMessage(String data) { int workthreadnumber; int iothreadnumber; // 取得線程池中可用的線程,把取得的可用任務者線程數目賦給workthreadnumber變量 // 取得的可用I/O線程數目給iothreadnumber變量 ThreadPool.GetAvailableThreads(out workthreadnumber, out iothreadnumber); Console.WriteLine("{0}\n CurrentThreadId is {1}\n CurrentThread is background :{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is: {4}\n", data, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsBackground.ToString(), workthreadnumber.ToString(), iothreadnumber.ToString()); } } }
運轉成果:
這裡有個須要留意的成績:假如年夜家測試的時刻, 應當把開端生成的text.txt文件放到該工程下bin\debug\目次下, 我剛開端的做的時刻就忘卻拷曩昔的, 讀出來的數據長度一向為0(這裡我犯的毛病寫下了,願望年夜家可以留意,也是小心本身要當心。)
2、I/O線程完成對要求的異步
我們異樣可以應用I/O線程來模仿對閱讀器對辦事器要求的異步操作,在.net類庫中的WebRequest類供給了異步要求的支撐,
上面就來演示下若何完成要求異步:
using System; using System.Net; using System.Threading; namespace RequestSample { class Program { static void Main(string[] args) { ThreadPool.SetMaxThreads(1000, 1000); PrintMessage("Main Thread start"); // 收回一個異步Web要求 WebRequest webrequest =WebRequest.Create("http://www.cnblogs.com/"); webrequest.BeginGetResponse(ProcessWebResponse, webrequest); Console.Read(); } // 回調辦法 private static void ProcessWebResponse(IAsyncResult result) { Thread.Sleep(500); PrintMessage("Asynchronous Method start"); WebRequest webrequest = (WebRequest)result.AsyncState; using (WebResponse webresponse = webrequest.EndGetResponse(result)) { Console.WriteLine("Content Length is : "+webresponse.ContentLength); } } // 打印線程池信息 private static void PrintMessage(String data) { int workthreadnumber; int iothreadnumber; // 取得線程池中可用的線程,把取得的可用任務者線程數目賦給workthreadnumber變量 // 取得的可用I/O線程數目給iothreadnumber變量 ThreadPool.GetAvailableThreads(out workthreadnumber, out iothreadnumber); Console.WriteLine("{0}\n CurrentThreadId is {1}\n CurrentThread is background :{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is: {4}\n", data, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsBackground.ToString(), workthreadnumber.ToString(), iothreadnumber.ToString()); } } }
運轉成果為:
寫到這裡這篇關於I/O線程的文章也差不多寫完了, 其實I/O線程還可以做許多工作,在收集(Socket)編程,web開辟中都邑用I/O線程,原來想寫個Demo來展現多線程在現實的任務中都有那些運用的處所的, 然則前面認為照樣等多線程系列都講完後再把常識一路串連起來做個Demo會好點,至於前面文章中將引見下線程同步的成績。