這裡說的非同步編程並不是AJAX等的Web非同步編程,而僅僅是DotNet中多線程的非同步編程.這種多線程的非同步編程主要用來解決某些受計算操作影響而引起主線程阻塞的問題.讓程式(主要是表單應用程式)看跑得更流暢.在dotnet的CLR以及API方法中有簡單易用的方法供我們實現非同步編程,並且都有相似的調用方法,諸如BeginXXX,EndXXX,IAsyncResult對象,同時也都涉及到回調,委託等操作.下面是一些簡單的應用
1.非同步IO操作,基本上就是按參數傳遞
非同步IO
1// 值得注意的是最好給定FileOptions.Asynchronous,相對效率會高些
2 FileStream fs = new FileStream("E:\\test.txt", FileMode.Open, FileAccess.Read, FileShare.Read, 1024, FileOptions.Asynchronous);
3 byte[] data = new byte[(int)fs.Length];
4
5 // 開始讀取
6 fs.BeginRead(data, 0, data.Length, delegate (IAsyncResult ar)
7 {
8 // 這裡是讀取結束之後回調的委託方法內容
9 fs.EndRead(ar);
10 fs.Close();
11
12 string content = Encoding.Default.GetString(data);
13 Console.WriteLine(content);
14 }, fs);
2.讀取資料庫內容的非同步作業,這裡的代碼是用在表單程式中,涉及到一個跨線程改變表單控制項的問題,但是在表單裡,只有通過表單的主線程來改變控制項的行為.如下非同步讀取資料,讀取資料的操作是在另外一個線程中,因此試圖在這個線程中操作表單控制項是徒勞的,還會出異常.所以只能通過表單的invoke方法,調用一個委託,這樣才能實現.當然這裡只是為了提出這個問題,其他的解決的方法還是有的,比如效率更低的輪詢方法.
資料訪問
1// 這個委託 用於在表單的主線程中調用
2 private delegate void FillGridHandler(SqlDataReader reader);
3 private void AsnDataAccess()
4 {
5 // 對於非同步作業的資料訪問,連接字串裡必須設定Async=True
6 string conStr = ConfigurationManager.ConnectionStrings["NorthWind"].ConnectionString;
7 SqlConnection con = new SqlConnection(conStr);
8 SqlCommand command = new SqlCommand("select [CompanyName] from [Suppliers]", con);
9
10 con.Open();
11 command.BeginExecuteReader(delegate(IAsyncResult ar)
12 {
13 SqlDataReader reader = command.EndExecuteReader(ar);
14
15 // 對於表單應用程式的 GridView的綁定
16 FillGridHandler fillGridHandler = delegate(SqlDataReader reader1)
17 {
18 DataTable dt = new DataTable();
19 dt.Load(reader1);
20 reader.Close();
21 dataGridView1.DataSource = dt;
22 };
23
24 // 用表單自身的線程去觸發委託方法 才能改變表單裡控制項屬性
25 this.Invoke(fillGridHandler, reader);
26 }, command, System.Data.CommandBehavior.CloseConnection);
27 }
3.非同步觸發委託的方法,非同步編程離不開委託,其本身也就是調用了委託的非同步方法呼叫,其內部就必定有一個委派物件委託非同步
1 delegate int CalSumHandler(int number);
2 private static void DelegateAsyn()
3 {
4 CalSumHandler handler = delegate(int number)
5 {
6 int sum = 0;
7 for (int i = 0; i < number; i++)
8 {
9 sum += i;
10 }
11 return sum;
12 };
13
14 int n = 10;
15 handler.BeginInvoke(n, delegate(IAsyncResult ar)
16 {
17 int res = handler.EndInvoke(ar);
18 Console.WriteLine("result from asyndelegate,sum = {0}", res);
19 }, n);
20 }