国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C# > 正文

C#編程總結(六)詳解異步編程

2020-01-24 00:55:35
字體:
來源:轉載
供稿:網友

1、什么是異步?

異步操作通常用于執行完成時間可能較長的任務,如打開大文件、連接遠程計算機或查詢數據庫。異步操作在主應用程序線程以外的線程中執行。應用程序調用方法異步執行某個操作時,應用程序可在異步方法執行其任務時繼續執行。

2、同步與異步的區別

同步(Synchronous):在執行某個操作時,應用程序必須等待該操作執行完成后才能繼續執行。

異步(Asynchronous):在執行某個操作時,應用程序可在異步操作執行時繼續執行。實質:異步操作,啟動了新的線程,主線程與方法線程并行執行。

3、異步和多線程的區別   

我們已經知道,異步的實質是開啟了新的線程。它與多線程的區別是什么呢?

簡單的說就是:異步線程是由線程池負責管理,而多線程,我們可以自己控制,當然在多線程中我們也可以使用線程池。

就拿網絡扒蟲而言,如果使用異步模式去實現,它使用線程池進行管理。異步操作執行時,會將操作丟給線程池中的某個工作線程來完成。當開始I/O操作的時候,異步會將工作線程還給線程池,這意味著獲取網頁的工作不會再占用任何CPU資源了。直到異步完成,即獲取網頁完畢,異步才會通過回調的方式通知線程池。可見,異步模式借助于線程池,極大地節約了CPU的資源。

注:DMA(Direct Memory Access)直接內存存取,顧名思義DMA功能就是讓設備可以繞過處理器,直接由內存來讀取資料。通過直接內存訪問的數據交換幾乎可以不損耗CPU的資源。在硬件中,硬盤、網卡、聲卡、顯卡等都有直接內存訪問功能。異步編程模型就是讓我們充分利用硬件的直接內存訪問功能來釋放CPU的壓力。

兩者的應用場景:

計算密集型工作,采用多線程。

IO密集型工作,采用異步機制。

4、異步應用

.NET Framework 的許多方面都支持異步編程功能,這些方面包括:

      1)文件 IO、流 IO、套接字 IO。

      2)網絡。

      3)遠程處理信道(HTTP、TCP)和代理。

      4)使用 ASP.NET 創建的 XML Web services。

      5)ASP.NET Web 窗體。

      6)使用 MessageQueue 類的消息隊列。

.NET Framework 為異步操作提供兩種設計模式:

      1)使用 IAsyncResult 對象的異步操作。

      2)使用事件的異步操作。

IAsyncResult 設計模式允許多種編程模型,但更加復雜不易學習,可提供大多數應用程序都不要求的靈活性。可能的話,類庫設計者應使用事件驅動模型實現異步方法。在某些情況下,庫設計者還應實現基于 IAsyncResult 的模型。

使用 IAsyncResult 設計模式的異步操作是通過名為 Begin操作名稱和End操作名稱的兩個方法來實現的,這兩個方法分別開始和結束異步操作操作名稱。例如,FileStream 類提供 BeginRead 和 EndRead 方法來從文件異步讀取字節。這兩個方法實現了 Read 方法的異步版本。在調用 Begin操作名稱后,應用程序可以繼續在調用線程上執行指令,同時異步操作在另一個線程上執行。每次調用 Begin操作名稱 時,應用程序還應調用 End操作名稱來獲取操作的結果。Begin操作名稱 方法開始異步操作操作名稱并返回一個實現 IAsyncResult 接口的對象。 .NET Framework 允許您異步調用任何方法。定義與您需要調用的方法具有相同簽名的委托;公共語言運行庫將自動為該委托定義具有適當簽名的 BeginInvoke 和 EndInvoke 方法。  

IAsyncResult 對象存儲有關異步操作的信息。下表提供了有關異步操作的信息。

名稱        

說明

AsyncState

獲取用戶定義的對象,它限定或包含關于異步操作的信息。

AsyncWaitHandle

獲取用于等待異步操作完成的 WaitHandle。

CompletedSynchronously

獲取一個值,該值指示異步操作是否同步完成。

IsCompleted

獲取一個值,該值指示異步操作是否已完

5、應用實例

案例1-讀取文件

通常讀取文件是一個比較耗時的工作,特別是讀取大文件的時候,常見的上傳和下載。但是我們又不想讓用戶一直等待,用戶同樣可以進行其他操作,可以使得系統有良好的交互性。這里我們寫了同步調用和異步調用來進行比較說明。

讀取文件類

using System;using System.IO;using System.Threading;namespace AsynSample{  class FileReader  {    /// <summary>    /// 緩存池    /// </summary>    private byte[] Buffer { get; set; }    /// <summary>    /// 緩存區大小    /// </summary>    public int BufferSize { get; set; }    public FileReader(int bufferSize)    {      this.BufferSize = bufferSize;      this.Buffer = new byte[BufferSize];    }    /// <summary>    /// 同步讀取文件    /// </summary>    /// <param name="path">文件路徑</param>    public void SynsReadFile(string path)    {      Console.WriteLine("同步讀取文件 begin");      using (FileStream fs = new FileStream(path, FileMode.Open))      {                fs.Read(Buffer, 0, BufferSize);        string output = System.Text.Encoding.UTF8.GetString(Buffer);        Console.WriteLine("讀取的文件信息:{0}",output);      }            Console.WriteLine("同步讀取文件 end");    }    /// <summary>    /// 異步讀取文件    /// </summary>    /// <param name="path"></param>    public void AsynReadFile(string path)    {      Console.WriteLine("異步讀取文件 begin");      //執行Endread時報錯,fs已經釋放,注意在異步中不能使用釋放需要的資源      //using (FileStream fs = new FileStream(path, FileMode.Open))      //{      //  Buffer = new byte[BufferSize];      //  fs.BeginRead(Buffer, 0, BufferSize, AsyncReadCallback, fs);      //}       if (File.Exists(path))      {        FileStream fs = new FileStream(path, FileMode.Open);        fs.BeginRead(Buffer, 0, BufferSize, AsyncReadCallback, fs);      }      else      {        Console.WriteLine("該文件不存在");      }    }    /// <summary>    ///     /// </summary>    /// <param name="ar"></param>    void AsyncReadCallback(IAsyncResult ar)    {      FileStream stream = ar.AsyncState as FileStream;      if (stream != null)      {        Thread.Sleep(1000);        //讀取結束        stream.EndRead(ar);        stream.Close();        string output = System.Text.Encoding.UTF8.GetString(this.Buffer);        Console.WriteLine("讀取的文件信息:{0}", output);      }    }  }}

測試用例

using System;using System.Threading;namespace AsynSample{  class Program  {    static void Main(string[] args)    {      FileReader reader = new FileReader(1024);      //改為自己的文件路徑      string path = "C://Windows//DAI.log";      Console.WriteLine("開始讀取文件了...");      //reader.SynsReadFile(path);      reader.AsynReadFile(path);      Console.WriteLine("我這里還有一大灘事呢.");      DoSomething();      Console.WriteLine("終于完事了,輸入任意鍵,歇著!");      Console.ReadKey();          }    /// <summary>    ///     /// </summary>    static void DoSomething()    {      Thread.Sleep(1000);      for (int i = 0; i < 10000; i++)      {        if (i % 888 == 0)        {          Console.WriteLine("888的倍數:{0}",i);        }      }    }  }}

輸出結果:

同步輸出:


異步輸出:


結果分析:

如果是同步讀取,在讀取時,當前線程讀取文件,只能等到讀取完畢,才能執行以下的操作

而異步讀取,是創建了新的線程,讀取文件,而主線程,繼續執行。我們可以開啟任務管理器來進行監視。

案例二--基于委托的異步操作

系統自帶一些類具有異步調用方式,如何使得自定義對象也具有異步功能呢?

我們可以借助委托來輕松實現異步。

說到BeginInvoke,EndInvoke就不得不停下來看一下委托的本質。為了便于理解委托,我定義一個簡單的委托:

public delegate string MyFunc(int num, DateTime dt);

我們再來看一下這個委托在編譯后的程序集中是個什么樣的:

委托被編譯成一個新的類型,擁有BeginInvoke,EndInvoke,Invoke這三個方法。前二個方法的組合使用便可實現異步調用。第三個方法將以同步的方式調用。 其中BeginInvoke方法的最后二個參數用于回調,其它參數則與委托的包裝方法的輸入參數是匹配的。 EndInvoke的返回值與委托的包裝方法的返回值匹配。

異步實現文件下載:

using System;using System.Text;namespace AsynSample{  /// <summary>  /// 下載委托  /// </summary>  /// <param name="fileName"></param>  public delegate string AysnDownloadDelegate(string fileName);  /// <summary>  /// 通過委托實現異步調用  /// </summary>  class DownloadFile  {    /// <summary>    /// 同步下載    /// </summary>    /// <param name="fileName"></param>    public string Downloading(string fileName)    {      string filestr = string.Empty;      Console.WriteLine("下載事件開始執行");      System.Threading.Thread.Sleep(3000);      Random rand = new Random();      StringBuilder builder =new StringBuilder();      int num;      for(int i=0;i<100;i++)      {        num = rand.Next(1000);        builder.Append(i);      }      filestr = builder.ToString();      Console.WriteLine("下載事件執行結束");      return filestr;    }    /// <summary>    /// 異步下載    /// </summary>    public IAsyncResult BeginDownloading(string fileName)    {      string fileStr = string.Empty;      AysnDownloadDelegate downloadDelegate = new AysnDownloadDelegate(Downloading);      return downloadDelegate.BeginInvoke(fileName, Downloaded, downloadDelegate);    }    /// <summary>    /// 異步下載完成后事件    /// </summary>    /// <param name="result"></param>    private void Downloaded(IAsyncResult result)    {      AysnDownloadDelegate aysnDelegate = result.AsyncState as AysnDownloadDelegate;      if (aysnDelegate != null)      {        string fileStr = aysnDelegate.EndInvoke(result);        if (!string.IsNullOrEmpty(fileStr))        {          Console.WriteLine("下載文件:{0}", fileStr);        }        else        {          Console.WriteLine("下載數據為空!");        }      }      else      {        Console.WriteLine("下載數據為空!");      }    }  }}

通過案例,我們發現,使用委托能夠很輕易的實現異步。這樣,我們就可以自定義自己的異步操作了。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 瓮安县| 峡江县| 湾仔区| 龙州县| 金阳县| 怀化市| 宁国市| 叙永县| 仙居县| 台江县| 通州区| 萍乡市| 丹东市| 古田县| 延川县| 阿坝| 鄂托克旗| 河南省| 盐城市| 宿州市| 启东市| 通海县| 施甸县| 阿巴嘎旗| 亚东县| 西平县| 新平| 永济市| 扎兰屯市| 西华县| 闽侯县| 陕西省| 五峰| 舞钢市| 英超| 佛教| 西畴县| 阿巴嘎旗| 河池市| 集安市| 宜昌市|