<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
        

      C#基礎(chǔ)系列——異步編程初探:async和await

      前言:前面有篇從應(yīng)用層面上面介紹了下多線程的幾種用法,有博友就說到了async, await等新語(yǔ)法。確實(shí),沒有異步的多線程是單調(diào)的、乏味的,async和await是出現(xiàn)在C#5.0之后,它的出現(xiàn)給了異步并行變成帶來(lái)了很大的方便。異步編程涉及到的東西還是比較多,本篇還是先介紹下async和await的原理及簡(jiǎn)單實(shí)現(xiàn)。

      C#基礎(chǔ)系列目錄:

       

      之前的那篇 C#基礎(chǔ)系列——多線程的常見用法詳解 就講到了多線程new Thread()的方式對(duì)于有返回值類型的委托是沒有解決方案的,如果需要返回值,必須要依靠異步的方式。了解異步之前,我們先來(lái)看看Thread對(duì)象的升級(jí)版本Task對(duì)象:

      1、Task對(duì)象的前世今生:Task對(duì)象是.Net Framework 4.0之后出現(xiàn)的異步編程的一個(gè)重要對(duì)象。在一定程度上來(lái)說,Task對(duì)象可以理解Thread對(duì)象的一個(gè)升級(jí)產(chǎn)品。既然是升級(jí)產(chǎn)品,那它肯定有他的優(yōu)勢(shì),比如我們上面Thread對(duì)象不能解決的問題:對(duì)于有返回值類型的委托。Task對(duì)象就能簡(jiǎn)單的解決。

           static void Main(string[] args)
              {
                  Console.WriteLine("執(zhí)行GetReturnResult方法前的時(shí)間:" + DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
                  var strRes = Task.Run<string>(() => { return GetReturnResult(); });//啟動(dòng)Task執(zhí)行方法
                  Console.WriteLine("執(zhí)行GetReturnResult方法后的時(shí)間:" + DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
                  Console.WriteLine(strRes.Result);//得到方法的返回值
                  Console.WriteLine("得到結(jié)果后的時(shí)間:" + DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
      
                  Console.ReadLine();
              }
      
              static string GetReturnResult()
              {
                  Thread.Sleep(2000);
                  return "我是返回值";
              }

      先來(lái)看結(jié)果:

      從結(jié)果分析可知在執(zhí)行var strRes = Task.Run<string>(() => { return GetReturnResult(); })這一句后,主線程并沒有阻塞去執(zhí)行GetReturnResult()方法,而是開啟了另一個(gè)線程去執(zhí)行GetReturnResult()方法。直到執(zhí)行strRes.Result這一句的時(shí)候主線程才會(huì)等待GetReturnResult()方法執(zhí)行完畢。為什么說是開啟了另一個(gè)線程,我們通過線程ID可以看得更清楚:

           static void Main(string[] args)
              {
                  Console.WriteLine("執(zhí)行GetReturnResult方法前的時(shí)間:" + DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
                  var strRes = Task.Run<string>(() => { return GetReturnResult(); });
                  Console.WriteLine("執(zhí)行GetReturnResult方法后的時(shí)間:" + DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
                  Console.WriteLine("我是主線程,線程ID:" + Thread.CurrentThread.ManagedThreadId);
                  Console.WriteLine(strRes.Result);
                  Console.WriteLine("得到結(jié)果后的時(shí)間:" + DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
      
                  Console.ReadLine();
              }
      
              static string GetReturnResult()
              {
                  Console.WriteLine("我是GetReturnResult里面的線程,線程ID:" + Thread.CurrentThread.ManagedThreadId);
                  Thread.Sleep(2000);
                  return "我是返回值";
              }

      結(jié)果:

      由此可以得知,Task.Run<string>(()=>{}).Reslut是阻塞主線程的,因?yàn)橹骶€程要得到返回值,必須要等方法執(zhí)行完成。

      Task對(duì)象的用法如下:

                  //用法一
                  Task task1 = new Task(new Action(MyAction));
                //用法二
                  Task task2 = new Task(delegate
                  {
                      MyAction();
                  });
              //用法三
                  Task task3 = new Task(() => MyAction());
                  Task task4 = new Task(() =>
                  {
                      MyAction();
                  });
      
                  task1.Start();
                  task2.Start();
                  task3.Start();
                  task4.Start();

      由上可知,Task對(duì)象的構(gòu)造函數(shù)傳入的是一個(gè)委托,既然能傳入Action類型的委托,可想而知Action的16中類型的參數(shù)又可以派上用場(chǎng)了。于是乎Task對(duì)象參數(shù)的傳遞就不用多說了吧。詳見 C#基礎(chǔ)系列——委托和設(shè)計(jì)模式(一)里面Action委托的用法。

       

      2、初識(shí) async & await。

              static void Main(string[] args)
              {
                  Console.WriteLine("我是主線程,線程ID:{0}", Thread.CurrentThread.ManagedThreadId);
                  TestAsync();
                  Console.ReadLine();
              }
      
              static async Task TestAsync()
              {
                  Console.WriteLine("調(diào)用GetReturnResult()之前,線程ID:{0}。當(dāng)前時(shí)間:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
                  var name = GetReturnResult();
                  Console.WriteLine("調(diào)用GetReturnResult()之后,線程ID:{0}。當(dāng)前時(shí)間:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
                  Console.WriteLine("得到GetReturnResult()方法的結(jié)果:{0}。當(dāng)前時(shí)間:{1}", await name, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
              }
      
              static async Task<string> GetReturnResult()
              {
                  Console.WriteLine("執(zhí)行Task.Run之前, 線程ID:{0}", Thread.CurrentThread.ManagedThreadId);
                  return await Task.Run(() =>
                  {
                      Thread.Sleep(3000);
                      Console.WriteLine("GetReturnResult()方法里面線程ID: {0}", Thread.CurrentThread.ManagedThreadId);
                      return "我是返回值";
                  });
              }

      結(jié)果:

      我們來(lái)看看程序的執(zhí)行過程:

      由上面的結(jié)果可以得到如下結(jié)論:

      (1)在async標(biāo)識(shí)的方法體里面,如果沒有await關(guān)鍵字的出現(xiàn),那么這種方法和調(diào)用普通的方法沒什么區(qū)別。

      (2)在async標(biāo)識(shí)的方法體里面,在await關(guān)鍵字出現(xiàn)之前,還是主線程順序調(diào)用的,直到await關(guān)鍵字的出現(xiàn)才會(huì)出現(xiàn)線程阻塞。

      (3)await關(guān)鍵字可以理解為等待方法執(zhí)行完畢,除了可以標(biāo)記有async關(guān)鍵字的方法外,還能標(biāo)記Task對(duì)象,表示等待該線程執(zhí)行完畢。所以await關(guān)鍵字并不是針對(duì)于async的方法,而是針對(duì)async方法所返回給我們的Task。

      (4)是否async關(guān)鍵字只能標(biāo)識(shí)返回Task對(duì)象的方法呢。我們來(lái)試試:

      異步方法的返回類型必須為void、Task或者Task<T>類型。也就是說async要么是void,要么和Task關(guān)聯(lián)。

       

      3、除了await關(guān)鍵字,Task對(duì)象還有另外一種方式等待執(zhí)行結(jié)果。  

           static async Task TestAsync()
              {
                  Console.WriteLine("調(diào)用GetReturnResult()之前,線程ID:{0}。當(dāng)前時(shí)間:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
                  var name = GetReturnResult();
                  Console.WriteLine("調(diào)用GetReturnResult()之后,線程ID:{0}。當(dāng)前時(shí)間:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
                  Console.WriteLine("得到GetReturnResult()方法的結(jié)果:{0}。當(dāng)前時(shí)間:{1}", name.GetAwaiter().GetResult(), DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
              }

      這樣可以得到相同的結(jié)果。

      name.GetAwaiter()這個(gè)方法得到的是一個(gè)TaskAwaiter對(duì)象,這個(gè)對(duì)象表示等待完成的異步任務(wù)的對(duì)象,并提供結(jié)果的參數(shù)。所以除了能完成await關(guān)鍵字的等待之外,它還能做一些其他的操作。我們將TaskAwaiter轉(zhuǎn)到定義

      public struct TaskAwaiter<TResult> : ICriticalNotifyCompletion, INotifyCompletion
          {
              public bool IsCompleted { get; }
              public TResult GetResult();
              public void OnCompleted(Action continuation);
              public void UnsafeOnCompleted(Action continuation);
         }    

      IsCompleted:獲取一個(gè)值,該值指示異步任務(wù)是否已完成。

      GetResult():得到執(zhí)行的結(jié)果。這個(gè)方法和await關(guān)鍵字效果相同。

      OnCompleted():傳入一個(gè)委托,在任務(wù)執(zhí)行完成之后執(zhí)行。

      UnsafeOnCompleted():計(jì)劃與此 awaiter 相關(guān)異步任務(wù)的延續(xù)操作。

      由此可以看出,await關(guān)鍵字實(shí)際上就是調(diào)用了TaskAwaiter對(duì)象的GetResult()方法。

       

      posted @ 2015-08-16 14:43  懶得安分  閱讀(62419)  評(píng)論(22)    收藏  舉報(bào)
      主站蜘蛛池模板: 人妻系列中文字幕精品| 亚洲精品蜜桃久久久久久| 精品人妻系列无码天堂| 亚洲男人在线天堂| 夜色福利站WWW国产在线视频| 真人作爱90分钟免费看视频| 99人中文字幕亚洲区三| 亚洲国产精品无码一区二区三区 | 亚洲国产精品久久久久婷婷图片| 日本一区二区不卡精品| 最新午夜男女福利片视频| 人妻丝袜AV中文系列先锋影音| 人人澡人人透人人爽| 国产精品视频免费一区二区三区| 图片区小说区av区| 一个人在看www免费| 江山市| 亚洲中文字幕一区精品自| 国产卡一卡二卡三免费入口| 人妻系列中文字幕精品| 久久精品国产亚洲αv忘忧草| 午夜精品亚洲一区二区三区| 精品国产中文字幕av| 91精品国产午夜福利| 国产精品粉嫩嫩在线观看| 人妻在线中文字幕| 国产女人18毛片水真多1| 国产性生大片免费观看性| 亚洲精品不卡av在线播放| 超清无码一区二区三区| 精品亚洲精品日韩精品| 大屁股肥熟女流白浆| 精品久久丝袜熟女一二三| 亚洲日韩久热中文字幕| 神池县| 骚虎视频在线观看| 在线天堂最新版资源| 免费无码一区无码东京热| 18禁无遮拦无码国产在线播放| 91精品国产吴梦梦在线观看永久 | 亚洲高请码在线精品av|