非同步程式設計-非同步讀取檔案
阿新 • • 發佈:2018-12-03
這篇文章我們學習如何用非同步程式設計來讀取檔案。
使用System.IO.Stream類的非同步呼叫方法,對檔案out.txt進行非同步讀操作。
執行結果:
原始碼:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Runtime.Remoting.Contexts; using System.IO; namespace Test1_1 { class HelloWorld { static void Main(string[] args) { //例項化非同步I/O測試器 AsynchIOTester theApp = new AsynchIOTester("D:\\out.txt"); //建立回撥委託物件 AsyncCallback myCallBack = new AsyncCallback(OnReadDone); //開始非同步讀操作 IAsyncResult ar = theApp.InputStream.BeginRead( theApp.Buffer, //存放結果的快取 0, //偏移值 theApp.Buffer.Length, //緩衝大小 myCallBack, //回撥方法 theApp); //區域性狀態物件 Console.WriteLine("++++++主執行緒繼續工作+++++"); Thread.Sleep(1000); Console.WriteLine("\n\n++++++++主執行緒工作完成,執行了1秒,等待非同步呼叫完成\n"); Console.Read(); } //回撥方法 static void OnReadDone(IAsyncResult ar) { //獲取區域性狀態物件 AsynchIOTester test = (AsynchIOTester)ar.AsyncState; //結束非同步讀操作,返回讀取的位元組數 int bufferCount = test.InputStream.EndRead(ar); if (bufferCount > 0) { //模擬下一次讀取間隔0.1s,以免較快讀完 Thread.Sleep(100); //轉換成指對編碼的字串 string s = Encoding.GetEncoding("GB2312").GetString(test.Buffer, 0, bufferCount); Console.Write(s); //建立回撥委託物件 AsyncCallback myCallBack = new AsyncCallback(OnReadDone); //如果沒有讀完,再次非同步呼叫BeginRead test.InputStream.BeginRead(test.Buffer, 0, test.Buffer.Length, myCallBack, test); } } } //非同步I/O測試器 public class AsynchIOTester { private Stream inputStream; //輸入流 private byte[] buffer; //存入讀入資料的緩衝區 private string filename; public AsynchIOTester(string filename) //建構函式 { this.filename = filename; inputStream = File.OpenRead(filename); //開啟檔案 buffer = new byte[16]; //分配緩衝 } public byte[] Buffer { get { return buffer; } } public Stream InputStream { get { return inputStream ;} } } }
主執行緒首先建立了一個AsynchIOTester非同步I/O測試器物件(即theApp)。該物件包括輸入流,緩衝區等資訊。程式可以在回撥時獲取它。然後,主執行緒中聲明瞭一個AsyncCallBack型別的委託物件myCallback,用於建立回撥委託物件。該物件綁定了回撥方法OnReadDone()。接下來,呼叫BeginRead()方法,進行檔案的非同步讀取,之後我們使用Thread.Sleep(1000)來模擬需要執行的操作耗時1秒。這時,非同步呼叫已經開始,因為不希望一次非同步呼叫就讀完整個檔案,因此,將緩衝區設為16個位元組。
當讀取完成時,CLR將呼叫回撥方法OnReadDone()。在OnReadDone()方法中,我們首先用(AsynchIOTester)ar.AsyncState獲取呼叫開始時封裝的非同步I/O數。如果位元組數大於0,將緩衝轉換成字串並輸出,然後再次呼叫BeginRead,開始下一次非同步讀取,為避免因為較快讀完,而無法驗證是否進行了非同步呼叫,我們使用Thread.Sleep(100),使之在0.1秒後再進行下一個操作。