同步調用與異步調用

同步調用

委託的Invoke方法用來進行同步調用。同步調用也能夠叫阻塞調用,它將阻塞當前線程,而後執行調用,調用完畢後再繼續向下進行。
編程


異步調用

異步調用不阻塞線程,而是把調用塞到線程池中,程序主線程或UI線程能夠繼續執行。個人理解是雖然表面上沒有新開啓線程,但實際上異步調用時CLR自動爲你開啓了一個新線程。委託的異步調用經過Beginxxx和Endxxx來實現。這種方式稱爲APM 異步編程模型。app

Beginxxx : 開始一個異步的請求,調用線程池中一個線程來執行
返回IAsyncResult 對象(異步的核心). IAsyncResult 簡單的說,他存儲異步操做的狀態信息的一個接口,也能夠用他來結束當前異步。
注意: Beginxxx和Endxxx必須成對調用.即便不須要返回值,但Endxxx仍是必須調用,不然可能會形成內存泄漏。
異步

(1)定義委託:
        public delegate string MyDelegate(int abc);
        那麼對應的BeginInvoke和EndInvoke以下:

        public virtual IAsyncResult BeginInvoke(int abc, AsyncCallBack callback, object asyncState) 和 public virtual string                             EndInvoke(IAsyncResult asyncResult)async


(2)實例化委託:

        MyDelegate m_MyDelegate = fun異步編程

         fun與m_MyDelegate 具備相同簽名的方法函數

(3)調用:
        IAsyncResult  m_AsyncResult = m_MyDelegate.BeginInvoke(1, onComplete, asyncState); 
        此時CLR會打開一個新的線程去異步執行委託的方法fun,當fun執行結束時就回到調用方線程並調用onComplete。
        AsyncCallback 也是一個委託,它的參數永遠都是IAsyncResult ,並且這個參數就是BeginInvoke裏的asyncState參數。

   //回調方法onComplete方法的定義以下:
   public void onComplete(IAsyncResult  m_AsyncResult )
  {
      ...... //其它處理代碼
       string result = EndInvoke(m_AsyncResult );
      ...... //其它處理代碼

   }spa

BeginInvoke方法前部分的參數是用來給調用它的委託對象所代理的那個方法傳遞參數即傳給fun,最後兩個參數爲可選,第一個是用來聲明回調函數的方法名,第二個參數是 "傳遞額外的參數",在這裏是傳給onComplete。經過BeginInvoke方法的最後一個參數能夠在調用方和回調函數之間傳遞狀態,由於他自己是Object對象,咱們能夠傳遞任何對象。
線程

回調方法的參數永遠都是IAsyncResult ,沒辦法直接給回調方法傳遞本身想要的參數,因此只能經過asyncState來間接的傳遞給回調方法。代理

在回調函數中如何取得這個參數呢?AsyncResult 類封裝的AsyncState屬性保存了BeginInvoke 的最後一個參數,咱們能夠經過它獲得。關於這一部分的知識能夠看我另外一篇博客AsyncResult 類的使用。code

EndInvoke方法是在回調方法裏被調用來獲取執行結果。

注意EndInvoke和回調函數接收的參數都是BeginInvoke的返回值m_AsyncResult ,而EndInvoke的返回值正是委託方法的返回類型(在這裏就是string)。

下面MSDN的代碼示例演示如何使用 Dns 類中的異步方法來檢索用戶指定的計算機的域名系統 (DNS) 信息。 此示例建立一個引用 ProcessDnsInformation 方法的 AsyncCallback 委託。 對各個針對 DNS 信息發出的異步請求,將分別調用一次此方法。

/*
The following example demonstrates using asynchronous methods to
get Domain Name System information for the specified host computers.
This example uses a delegate to obtain the results of each asynchronous 
operation.
*/

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections.Specialized;
using System.Collections;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    public class UseDelegateForAsyncCallback
    {
        static int requestCounter;
        static ArrayList hostData = new ArrayList();
        static StringCollection hostNames = new StringCollection();
        static void UpdateUserInterface()
        {
            // Print a message to indicate that the application
            // is still working on the remaining requests.
            Console.WriteLine("{0} requests remaining.", requestCounter);
        }
        public static void Main()
        {
            // Create the delegate that will process the results of the 
            // asynchronous request.
            AsyncCallback callBack = new AsyncCallback(ProcessDnsInformation);//定義回調函數
            string host;
            do
            {
                Console.Write(" Enter the name of a host computer or <enter> to finish: ");
                host = Console.ReadLine();
                if (host.Length > 0)
                {
                    // Increment the request counter in a thread safe manner.
                    Interlocked.Increment(ref requestCounter);
                    // Start the asynchronous request for DNS information.
                    Dns.BeginGetHostEntry(host, callBack, host);
                 }
            } while (host.Length > 0);
            // The user has entered all of the host names for lookup.
            // Now wait until the threads complete.
            while (requestCounter > 0)
            {
                UpdateUserInterface();
            }
            // Display the results.
            for (int i = 0; i< hostNames.Count; i++)
            {
                object data = hostData [i];
                string message = data as string;
                // A SocketException was thrown.
                if (message != null)
                {
                    Console.WriteLine("Request for {0} returned message: {1}", 
                        hostNames[i], message);
                    continue;
                }
                // Get the results.
                IPHostEntry h = (IPHostEntry) data;
                string[] aliases = h.Aliases;
                IPAddress[] addresses = h.AddressList;
                if (aliases.Length > 0)
                {
                    Console.WriteLine("Aliases for {0}", hostNames[i]);
                    for (int j = 0; j < aliases.Length; j++)
                    {
                        Console.WriteLine("{0}", aliases[j]);
                    }
                }
                if (addresses.Length > 0)
                {
                    Console.WriteLine("Addresses for {0}", hostNames[i]);
                    for (int k = 0; k < addresses.Length; k++)
                    {
                        Console.WriteLine("{0}",addresses[k].ToString());
                    }
                }
            }
       }

        // The following method is called when each asynchronous operation completes.
        static void ProcessDnsInformation(IAsyncResult result)
        {
            string hostName = (string) result.AsyncState;//傳值
            hostNames.Add(hostName);
            try 
            {
                // Get the results.
                IPHostEntry host = Dns.EndGetHostEntry(result);//取結果
                hostData.Add(host);
            }
            // Store the exception message.
            catch (SocketException e)
            {
                hostData.Add(e.Message);
            }
            finally 
            {
                // Decrement the request counter in a thread-safe manner.
                Interlocked.Decrement(ref requestCounter);
            }
        }
    }
}
相關文章
相關標籤/搜索