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

首頁 > 學院 > 開發設計 > 正文

C#基礎——談談.NET異步編程的演變史

2019-11-17 03:21:54
字體:
來源:轉載
供稿:網友

C#基礎——談談.NET異步編程的演變史

前言

C#5.0最重要的改進,就是提供了更強大的異步編程。C#5.0僅增加兩個新的關鍵字:async和await。

使用異步編程,方法調用是在后臺運行(通常在線程或任務的幫助下),并且不會阻塞調用線程。

本文將介紹3種不同模式的異步編程:異步模式,基于事件的異步模式和新增加的基于任務的異步編程模式(TAP)。TAP是利用async和await關鍵字來實現的。通過這里的比較,將認識到新的增加的基于任務的異步模式的真正優勢。

假設情景:我們需要進行一個耗時操作(這里使用webclient對象下載百度首頁代碼),接下來通過同步以及上面談到的3種異步模式實現。

同步調用

創建一個控制臺應用程序:

static void Main(string[] args)        {            WebClient client = new WebClient();            client.Encoding = Encoding.UTF8;            string resp = client.DownloadString("http://www.baidu.com");            Console.WriteLine(resp);            //todo:其他操作            Console.ReadKey();        }

運行上述代碼,在執行DownloadString的時候,主線程會被阻塞,如果有用戶界面,那么用戶體驗肯定不好,而DownloadString這個方法的執行速度取決于網速等原因,所以在這種情況下,使用異步調用就非常有必要了。

異步模式

實現異步模式定義BeginXXX方法和EndXXX方法。例如,如果有一個同步方法DownloadString,異步方法將轉化成2個方法BeginDownloadString和EndDownloadString。BeginXXX異步方法接受同步方法的所有輸入參數以及一個AsyncCallback參數(一個委托,在異步方法執行完調用),返回一個IAsyncResult對象,用于驗證調用是否完成,EndXXX異步方法使用同步方法的所有輸出參數,并以同步方法的返回類型來返回結果(簡單來說就是獲取異步執行方法的返回值,如果在異步執行的方法還沒結束,則阻塞主線程直到異步方法執行結束)。

WebClient并沒有異步模式的實現,但是可以用HttpWebRequest類來代替(該類有BeginGetResponse和EndGetResponse):

static void Main(string[] args)        {            HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://www.baidu.com");            req.BeginGetResponse(ar =>            {                HttpWebResponse resp = (HttpWebResponse)req.EndGetResponse(ar);                Console.WriteLine(resp.ContentType );                //todo:其他操作            }, null);            Console.WriteLine("這是主線程");                        Console.ReadKey();        }

如果非要用WebClient來實現異步模式,則需要用委托(只給代碼不多做介紹了):

static void Main(string[] args)        {           //定義委托實例            Func<string, string> downloadString = url =>            {                WebClient client = new WebClient();                client.Encoding = Encoding.UTF8;              return client.DownloadString(url);                          };            //異步執行委托            downloadString.BeginInvoke("http://www.baidu.com", ar =>            {                string resp = downloadString.EndInvoke(ar);                Console.WriteLine(resp);            },null);            Console.WriteLine("這是主線程");                        Console.ReadKey();        }

異步模式的優勢是使用委托就能實現異步編程。不用改變程序的行為。也不會阻塞界面的操作。但是,使用異步模式的過程是非常復雜的(尤其在winform或wpf中涉及更新界面操作時)。幸運的是,.NET2.0推出了基于事件的異步模式,能很輕松更新界面。

基于事件的異步模式

基于事件的異步模式定義了一個帶有“Async”后綴的方法。例如:對于同步方法DownloadString,WebClient類提供一個異步變體方法DownloadStringAsync。異步方法完成后,不是定義被調用的委托,而是定義事件。當異步方法DownloadStringAsync完成后,會直接調用DownloadStringCompleted事件,實現方式和上面差不多。但這時可以直接訪問界面UI元素。

在這里我們換一個winform項目(界面只包含一個label和一個button),點擊button更新label值:

PRivate void button1_Click(object sender, EventArgs e)        {                       WebClient client = new WebClient();            client.Encoding = Encoding.UTF8;            client.DownloadStringCompleted += (sender1, e1) =>            {                string resp = e1.Result;                label1.Text = resp.Substring(10);            };            client.DownloadStringAsync(new Uri("http://www.baidu.com"));                      }

基于事件的異步模式的優勢在于易于使用。但是,如果在自定義類中實現這個模式,就沒那么簡單了。方法還是有的,可以使用BackgroundWorker類來實現異步調用同步方法。BackgroundWorker類實現了基于事件的異步模式。還有,這種模式與同步方法調用相比,順序顛倒了。調用異步方法之前,需要定義這個方法完成時發生什么。因此,下面進入異步編程的新世界,利用async和await關鍵字。

基于任務的異步模式(推薦使用)

這次先看代碼:

private async  void button1_Click(object sender, EventArgs e)        {                       WebClient client = new WebClient();            client.Encoding = Encoding.UTF8;          string resp=await client.DownloadStringTaskAsync("http://www.baidu.com");            label1.Text = resp.Substring(10);        }

在.NET4.5中,更新了WebClient類,提供了基于任務的異步模式。該模式定義了一個帶有“Async”后綴的方法,并返回一個Task類型。由于WebClient類已經提供了一個帶有“Async”后綴的方法,因此新方法名為DownloadStringTaskAsync。

DownloadStringTaskAsync方法聲明返回Task<string>類型。但是,不需要為DownloadStringTaskAsync方法返回的結果聲明一個Task<string>類型的變量。只要聲明一個string類型的變量,并且使用await關鍵字。await關鍵字不會阻塞完成其他任務的線程。當DownloadStringTaskAsync方法完成其后臺處理后,UI線程會繼續并從后臺線程中獲得結果,賦值給resp。同時,在await關鍵字的下一行代碼會繼續執行。

現在,代碼簡單多了。沒有阻塞,也不需要手工切回UI線程,這些都是自動實現的。代碼順序也和慣用的同步編程基本上一樣了。

轉換異步模式

并非.NET FrameWork的所有類在.NET 4.5中都引入了新的異步方法,有些類還是只提供了BeginXXX和EndXXX方法的異步模式,那怎么辦?

我們以上面用到的HttpWebResponse為例(假設它沒有新的異步方法):Task類型的泛型參數Task<WebResponse>,定義了調用方法的返回值類型,FromAsync方法的前兩個參數是委托類型,傳入對應的BeginXXX和EndXXX,由于我們沒有輸入參數,因而也沒有輸入參數的對象狀態,所有是null,代碼如下:

private async   void button1_Click(object sender, EventArgs e)        {            HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://www.baidu.com");            HttpWebResponse resp = (HttpWebResponse)await Task<WebResponse>.Factory.FromAsync(req.BeginGetResponse, req.EndGetResponse, null);        }

之前一直對這塊比較模糊,今天學了總結下,關于異步編程以及多線程還有好多東西要學,也很復雜,本文也就簡單介紹到這了

覺得好的“贊”一個唄,親


上一篇:[CLR via C#]10. 屬性

下一篇:Config文件

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 贵州省| 清涧县| 临西县| 临海市| 凌云县| 上饶县| 开阳县| 马山县| 安乡县| 柯坪县| 阜平县| 伊春市| 兰考县| 拜城县| 来凤县| 喀喇| 广灵县| 聂拉木县| 体育| 太仆寺旗| 芒康县| 钟祥市| 中牟县| 郑州市| 新密市| 晴隆县| 锦州市| 五河县| 庆阳市| 名山县| 乌海市| 秦安县| 四川省| 教育| 阿拉善盟| 信阳市| 大理市| 乌拉特后旗| 民权县| 乐陵市| 本溪|