以SOCKET通訊中的非同步方法為例:
public static ManualResetEvent ConnectDone = new ManualResetEvent(false);
公共靜態無效 ConnectCallback(IAsyncResult ar)
{
Socket sClient = (Socket)ar.AsyncState;
sClient.EndConnect(ar);
Console.WriteLine("套接字已連接到 {0}", sClient.RemoteEndPoint.ToString());
ConnectDone.Set();
}
公共靜態無效Main(字串[] arg)
{
嘗試
{
IPHostEntry ipHost = Dns.Resolve(“127.0.0.1”);
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint endPoint = new IPEndPoint(ipAddr, 11000);
Socket sClient = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
sClient.BeginConnect(endPoint, new AsyncCallback(ConnectCallback),
sClient);
for (int i = 0; i <5; i++)
Console.WriteLine("做一些其他工作。");
byte[] byteData = Encoding.ASCII.GetBytes("一些資料。");
ConnectDone.WaitOne();
sClient.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), sClient);
……
}
(註:ManualResetEvent 讓執行緒透過發送訊號相互通訊。通常,此通訊涉及一個執行緒在其他執行緒進行之前必須完成的任務。ManualResetEvent
就像一個訊號燈,可以利用它的訊號來通知其他執行緒。它有幾個重要的地方的方法:Reset(),Set(),WaitOne()。直到它的Reset()或Set()方法被調用,Reset()方法將其設定為無訊號狀態,Set()方法將其設定為有訊號狀態。有一個信號狀態,此時該線程將被激活。
本例中,主執行緒調用ConnectDone.WaitOne();之後,主執行緒阻塞,直到連接操作(即ConnectCallback)完成,因為連接操作完成之後,執行了ConnectDone.Set()將訊號燈設為有訊號,由於調用了ManualResetEvent.WaitOne()方法而初始化等待狀態的主執行緒將會接收到這個訊號,於是它繼續往下執行,完成後面的工作。
同步與非同步:
簡單來說,同步即程式執行一個方法,等該方法返回之後,繼續往下走,非
同步:即程式呼叫一個方法後立即返回,「宏」而言,主執行緒與方法執行緒執行緒執行
就本例而言,socket的非同步方法BeginConnect被呼叫後,繼續執行主執行緒中該語句之後的程式碼,即:
for (int
i = 0; i <5; i++)
Console.WriteLine("Do Some Other工作。
byte[] byteData = Encoding.ASCII.GetBytes("Some Data.");
如果呼叫的是同步方法,那麼,必須輸出「Socket連線到…」一定會在「Do Some Other Work.」之前,因為主執行緒等待同步方法的返回,但是在非同步的情況下,將可能在5 行「Do Some Other Work.」之間的某個時刻出現「Socket 連接到...」的輸出(實際情況還是依賴網路的
執行緒調度
)。