深入分析C#非同步編程詳解

來源:互聯網
上載者:User

同步方法和非同步方法呼叫的區別
同步方法調用在程式繼續執行之前需要等待同步方法執行完畢返回結果
非同步方法呼叫則在被調用之後立即返回以便程式在被呼叫者法完成其任務的同時執行其它操作
非同步編程概覽
.NET Framework 允許您非同步呼叫任何方法。定義與您需要調用的方法具有相同簽名的委託;公用語言運行庫將自動為該委託定義具有適當簽名
的 BeginInvoke 和 EndInvoke 方法。
BeginInvoke 方法用於啟動非同步呼叫。它與您需要非同步執行的方法具有相同的參數,只不過還有兩個額外的參數(將在稍後描述)。
BeginInvoke 立即返回,不等待非同步呼叫完成。
BeginInvoke 返回 IasyncResult,可用於監視調用進度。
EndInvoke 方法用於檢索非同步呼叫結果。調用 BeginInvoke 後可隨時調用 EndInvoke 方法;如果非同步呼叫未完成,EndInvoke 將一直阻塞到
非同步呼叫完成。EndInvoke 的參數包括您需要非同步執行的方法的 out 和 ref 參數(在 Visual Basic 中為 <Out> ByRef 和 ByRef)以及由
BeginInvoke 返回的 IAsyncResult。
四種使用 BeginInvoke 和 EndInvoke 進行非同步呼叫的常用方法。調用了 BeginInvoke 後,可以:
1.進行某些操作,然後調用 EndInvoke 一直阻塞到調用完成。
2.使用 IAsyncResult.AsyncWaitHandle 擷取 WaitHandle,使用它的 WaitOne 方法將執行一直阻塞到發出 WaitHandle 訊號,然後調用
EndInvoke。這裡主要是主程式等待非同步方法呼叫,等待非同步方法呼叫的結果。
3.輪詢由 BeginInvoke 返回的 IAsyncResult,IAsyncResult.IsCompeted確定非同步呼叫何時完成,然後調用 EndInvoke。此處理個人認為與
相同。
4.將用於回調方法的委託傳遞給 BeginInvoke。該方法在非同步呼叫完成後在 ThreadPool 線程上執行,它可以調用 EndInvoke。這是在強制裝
換回呼函數裡面IAsyncResult.AsyncState(BeginInvoke方法的最後一個參數)成委託,然後用委託執行EndInvoke。
警告 始終在非同步呼叫完成後調用 EndInvoke。
以上有不理解的稍後可以再理解。

例子
1)先來個簡單的沒有回呼函數的非同步方法呼叫例子
請再運行程式的時候,仔細看注釋,對理解很有協助。還有,若將注釋的中的兩個方法都同步,你會發現非同步啟動並執行速度優越性。 複製代碼 代碼如下:using System;
namespace ConsoleApplication1
{
class Class1
{
//聲明委託
public delegate void AsyncEventHandler();

//非同步方法呼叫
void Event1()
{
Console.WriteLine("Event1 Start");
System.Threading.Thread.Sleep(4000);
Console.WriteLine("Event1 End");
}
// 同步方法
void Event2()
{
Console.WriteLine("Event2 Start");
int i=1;
while(i<1000)
{
i=i+1;
Console.WriteLine("Event2 "+i.ToString());
}
Console.WriteLine("Event2 End");
}
[STAThread]
static void Main(string[] args)
{
long start=0;
long end=0;
Class1 c = new Class1();
Console.WriteLine("ready");
start=DateTime.Now.Ticks;
//執行個體委託
AsyncEventHandler asy = new AsyncEventHandler(c.Event1);
//非同步呼叫開始,沒有回呼函數和AsyncState,都為null
IAsyncResult ia = asy.BeginInvoke(null, null);
//同步開始,
c.Event2();
//非同步結束,若沒有結束,一直阻塞到調用完成,在此返回該函數的return,若有傳回值。

asy.EndInvoke(ia);
//都同步的情況。
//c.Event1();
//c.Event2();

end =DateTime.Now.Ticks;
Console.WriteLine("時幅差="+ Convert.ToString(end-start) );
Console.ReadLine();
}
}
}

2)下面看有回呼函數的WebRequest和WebResponse的非同步作業。
複製代碼 代碼如下:using System;
using System.Net;
using System.Threading;
using System.Text;
using System.IO;
// RequestState 類用於通過
// 非同步呼叫傳遞資料
public class RequestState
{
const int BUFFER_SIZE = 1024;
public StringBuilder RequestData;
public byte[] BufferRead;
public HttpWebRequest Request;
public Stream ResponseStream;
// 建立適當編碼類別型的解碼器
public Decoder StreamDecode = Encoding.UTF8.GetDecoder();
public RequestState()
{
BufferRead = new byte[BUFFER_SIZE];
RequestData = new StringBuilder("");
Request = null;
ResponseStream = null;
}
}
// ClientGetAsync 發出非同步請求
class ClientGetAsync
{
public static ManualResetEvent allDone = new ManualResetEvent(false);
const int BUFFER_SIZE = 1024;
public static void Main(string[] args)
{
if (args.Length < 1)
{
showusage();
return;
}
// 從命令列擷取 URI
Uri HttpSite = new Uri(args[0]);
// 建立請求對象
HttpWebRequest wreq = (HttpWebRequest)WebRequest.Create(HttpSite);
// 建立狀態物件
RequestState rs = new RequestState();
// 將請求添加到狀態,以便它可以被來回傳遞
rs.Request = wreq;
// 發出非同步請求
IAsyncResult r = (IAsyncResult)wreq.BeginGetResponse(new AsyncCallback(RespCallback), rs);
// 將 ManualResetEvent 設定為 Wait,
// 以便在調用回調前,應用程式不退出
allDone.WaitOne();
}
public static void showusage()
{
Console.WriteLine("嘗試擷取 (GET) 一個 URL");
Console.WriteLine("\r\n用法::");
Console.WriteLine("ClientGetAsync URL");
Console.WriteLine("樣本::");
Console.WriteLine("ClientGetAsync http://www.microsoft.com/net/");
}
private static void RespCallback(IAsyncResult ar)
{
// 從非同步結果擷取 RequestState 對象
RequestState rs = (RequestState)ar.AsyncState;
// 從 RequestState 擷取 HttpWebRequest
HttpWebRequest req = rs.Request;
// 調用 EndGetResponse 產生 HttpWebResponse 對象
// 該對象來自上面發出的請求
HttpWebResponse resp = (HttpWebResponse)req.EndGetResponse(ar);
// 既然我們擁有了響應,就該從
// 響應流開始讀取資料了
Stream ResponseStream = resp.GetResponseStream();
// 該讀取操作也使用非同步完成,所以我們
// 將要以 RequestState 儲存流
rs.ResponseStream = ResponseStream;
// 請注意,rs.BufferRead 被傳入到 BeginRead。
// 這是資料將被讀入的位置。
IAsyncResult iarRead = ResponseStream.BeginRead(rs.BufferRead, 0, BUFFER_SIZE, new AsyncCallback(ReadCallBack), rs);
}
private static void ReadCallBack(IAsyncResult asyncResult)
{
// 從 asyncresult 擷取 RequestState 對象
RequestState rs = (RequestState)asyncResult.AsyncState;
// 取出在 RespCallback 中設定的 ResponseStream
Stream responseStream = rs.ResponseStream;
// 此時 rs.BufferRead 中應該有一些資料。
// 讀取操作將告訴我們那裡是否有資料
int read = responseStream.EndRead(asyncResult);
if (read > 0)
{
// 準備 Char 數組緩衝區,用於向 Unicode 轉換
Char[] charBuffer = new Char[BUFFER_SIZE];
// 將位元組流轉換為 Char 數組,然後轉換為字串
// len 顯示多少字元被轉換為 Unicode
int len = rs.StreamDecode.GetChars(rs.BufferRead, 0, read, charBuffer, 0);
String str = new String(charBuffer, 0, len);
// 將最近讀取的資料追加到 RequestData stringbuilder 對象中,
// 該對象包含在 RequestState 中
rs.RequestData.Append(str);
// 現在發出另一個非同步呼叫,讀取更多的資料
// 請注意,將不斷調用此過程,直到
// responseStream.EndRead 返回 -1
IAsyncResult ar = responseStream.BeginRead(rs.BufferRead, 0, BUFFER_SIZE, new AsyncCallback(ReadCallBack), rs);
}
else
{
if (rs.RequestData.Length > 1)
{
// 所有資料都已被讀取,因此將其顯示到控制台
string strContent;
strContent = rs.RequestData.ToString();
Console.WriteLine(strContent);
}
// 關閉響應流
responseStream.Close();
// 設定 ManualResetEvent,以便主線程可以退出
allDone.Set();
}
return;
}
}

在這裡有回呼函數,且非同步回調中又有非同步作業。
首先是非同步獲得ResponseStream,然後非同步讀取資料。
這個程式非常經典。從中可以學到很多東西的。我們來共同探討。
總結
上面說過,.net framework 可以非同步呼叫任何方法。所以非同步用處廣泛。
在.net framework 類庫中也有很多非同步呼叫的方法。一般都是已Begin開頭End結尾構成一對,非同步委託方法,外加兩個回呼函數和AsyncState參數,組成非同步作業的宏觀體現。所以要做非同步編程,不要忘了委託delegate、Begin,End,AsyncCallBack委託,AsyncState執行個體(在回呼函數中通過IAsyncResult.AsyncState來強制轉換),IAsycResult(監控非同步),就足以理解非同步真諦了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.