亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

詳解C#中 Thread,Task,Async/Await,IAsyncResult的那些事兒

2019-10-29 21:15:43
字體:
來源:轉載
供稿:網友

說起異步,Thread,Task,async/await,IAsyncResult 這些東西肯定是繞不開的,今天就來依次聊聊他們

1.線程(Thread)

多線程的意義在于一個應用程序中,有多個執行部分可以同時執行;對于比較耗時的操作(例如io,數據庫操作),或者等待響應(如WCF通信)的操作,可以單獨開啟后臺線程來執行,這樣主線程就不會阻塞,可以繼續往下執行;等到后臺線程執行完畢,再通知主線程,然后做出對應操作!

在C#中開啟新線程比較簡單

static void Main(string[] args){ Console.WriteLine("主線程開始"); //IsBackground=true,將其設置為后臺線程 Thread t = new Thread(Run) { IsBackground = true }; t.Start();   Console.WriteLine("主線程在做其他的事!"); //主線程結束,后臺線程會自動結束,不管有沒有執行完成 //Thread.Sleep(300); Thread.Sleep(1500); Console.WriteLine("主線程結束");}static void Run(){ Thread.Sleep(700); Console.WriteLine("這是后臺線程調用");}

執行結果如下圖,

Thread,Task,Async/Await,IAsyncResult

可以看到在啟動后臺線程之后,主線程繼續往下執行了,并沒有等到后臺線程執行完之后。

1.1 線程池

試想一下,如果有大量的任務需要處理,例如網站后臺對于HTTP請求的處理,那是不是要對每一個請求創建一個后臺線程呢?顯然不合適,這會占用大量內存,而且頻繁地創建的過程也會嚴重影響速度,那怎么辦呢?線程池就是為了解決這一問題,把創建的線程存起來,形成一個線程池(里面有多個線程),當要處理任務時,若線程池中有空閑線程(前一個任務執行完成后,線程不會被回收,會被設置為空閑狀態),則直接調用線程池中的線程執行(例asp.net處理機制中的Application對象),

使用事例:

for (int i = 0; i < 10; i++){ ThreadPool.QueueUserWorkItem(m => {  Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString()); });}Console.Read();

運行結果:

Thread,Task,Async/Await,IAsyncResult

可以看到,雖然執行了10次,但并沒有創建10個線程。

 1.2 信號量(Semaphore)

 Semaphore負責協調線程,可以限制對某一資源訪問的線程數量

 這里對SemaphoreSlim類的用法做一個簡單的事例:

 static SemaphoreSlim semLim = new SemaphoreSlim(3); //3表示最多只能有三個線程同時訪問static void Main(string[] args){ for (int i = 0; i < 10; i++) {  new Thread(SemaphoreTest).Start(); } Console.Read();}static void SemaphoreTest(){ semLim.Wait(); Console.WriteLine("線程" + Thread.CurrentThread.ManagedThreadId.ToString() + "開始執行"); Thread.Sleep(2000); Console.WriteLine("線程" + Thread.CurrentThread.ManagedThreadId.ToString() + "執行完畢"); semLim.Release();}

執行結果如下:

Thread,Task,Async/Await,IAsyncResultThread,Task,Async/Await,IAsyncResult

可以看到,剛開始只有三個線程在執行,當一個線程執行完畢并釋放之后,才會有新的線程來執行方法!

除了SemaphoreSlim類,還可以使用Semaphore類,感覺更加靈活,感興趣的話可以搜一下,這里就不做演示了!

2.Task

Task是.NET4.0加入的,跟線程池ThreadPool的功能類似,用Task開啟新任務時,會從線程池中調用線程,而Thread每次實例化都會創建一個新的線程。

Console.WriteLine("主線程啟動");//Task.Run啟動一個線程//Task啟動的是后臺線程,要在主線程中等待后臺線程執行完畢,可以調用Wait方法//Task task = Task.Factory.StartNew(() => { Thread.Sleep(1500); Console.WriteLine("task啟動"); });Task task = Task.Run(() => {  Thread.Sleep(1500); Console.WriteLine("task啟動");});Thread.Sleep(300);task.Wait();Console.WriteLine("主線程結束");

執行結果如下:

Thread,Task,Async/Await,IAsyncResult

開啟新任務的方法:Task.Run()或者Task.Factory.StartNew(),開啟的是后臺線程

要在主線程中等待后臺線程執行完畢,可以使用Wait方法(會以同步的方式來執行)。不用Wait則會以異步的方式來執行。

比較一下Task和Thread:

static void Main(string[] args){ for (int i = 0; i < 5; i++) {  new Thread(Run1).Start(); } for (int i = 0; i < 5; i++) {  Task.Run(() => { Run2(); }); }}static void Run1(){ Console.WriteLine("Thread Id =" + Thread.CurrentThread.ManagedThreadId);}static void Run2(){ Console.WriteLine("Task調用的Thread Id =" + Thread.CurrentThread.ManagedThreadId);}

執行結果:

Thread,Task,Async/Await,IAsyncResult

可以看出來,直接用Thread會開啟5個線程,用Task(用了線程池)開啟了3個!

2.1 Task<TResult>

Task<TResult>就是有返回值的Task,TResult就是返回值類型。

Console.WriteLine("主線程開始");//返回值類型為stringTask<string> task = Task<string>.Run(() => { Thread.Sleep(2000);  return Thread.CurrentThread.ManagedThreadId.ToString(); });//會等到task執行完畢才會輸出;Console.WriteLine(task.Result);Console.WriteLine("主線程結束");

運行結果:

Thread,Task,Async/Await,IAsyncResult

通過task.Result可以取到返回值,若取值的時候,后臺線程還沒執行完,則會等待其執行完畢!

簡單提一下:

Task任務可以通過CancellationTokenSource類來取消,感覺用得不多,用法比較簡單,感興趣的話可以搜一下!

3. async/await

async/await是C#5.0中推出的,先上用法:

static void Main(string[] args){ Console.WriteLine("-------主線程啟動-------"); Task<int> task = GetStrLengthAsync(); Console.WriteLine("主線程繼續執行"); Console.WriteLine("Task返回的值" + task.Result); Console.WriteLine("-------主線程結束-------");}static async Task<int> GetStrLengthAsync(){ Console.WriteLine("GetStrLengthAsync方法開始執行"); //此處返回的<string>中的字符串類型,而不是Task<string> string str = await GetString(); Console.WriteLine("GetStrLengthAsync方法執行結束"); return str.Length;}static Task<string> GetString(){   //Console.WriteLine("GetString方法開始執行") return Task<string>.Run(() => {  Thread.Sleep(2000);  return "GetString的返回值"; });}

async用來修飾方法,表明這個方法是異步的,聲明的方法的返回類型必須為:void,Task或Task<TResult>。

await必須用來修飾Task或Task<TResult>,而且只能出現在已經用async關鍵字修飾的異步方法中。通常情況下,async/await成對出現才有意義,

看看運行結果:

Thread,Task,Async/Await,IAsyncResult

可以看出來,main函數調用GetStrLengthAsync方法后,在await之前,都是同步執行的,直到遇到await關鍵字,main函數才返回繼續執行。

那么是否是在遇到await關鍵字的時候程序自動開啟了一個后臺線程去執行GetString方法呢?

現在把GetString方法中的那行注釋加上,運行的結果是:

Thread,Task,Async/Await,IAsyncResult

大家可以看到,在遇到await關鍵字后,沒有繼續執行GetStrLengthAsync方法后面的操作,也沒有馬上反回到main函數中,而是執行了GetString的第一行,以此可以判斷await這里并沒有開啟新的線程去執行GetString方法,而是以同步的方式讓GetString方法執行,等到執行到GetString方法中的Task<string>.Run()的時候才由Task開啟了后臺線程!

那么await的作用是什么呢?

可以從字面上理解,上面提到task.wait可以讓主線程等待后臺線程執行完畢,await和wait類似,同樣是等待,等待Task<string>.Run()開始的后臺線程執行完畢,不同的是await不會阻塞主線程,只會讓GetStrLengthAsync方法暫停執行。

那么await是怎么做到的呢?有沒有開啟新線程去等待?

Thread,Task,Async/Await,IAsyncResult

只有兩個線程(主線程和Task開啟的線程)!至于怎么做到的(我也不知道......>_<),大家有興趣的話研究下吧!

4.IAsyncResult

IAsyncResult自.NET1.1起就有了,包含可異步操作的方法的類需要實現它,Task類就實現了該接口

Thread,Task,Async/Await,IAsyncResult

在不借助于Task的情況下怎么實現異步呢?

class Program{ static void Main(string[] args) {  Console.WriteLine("主程序開始--------------------");  int threadId;  AsyncDemo ad = new AsyncDemo();  AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);  IAsyncResult result = caller.BeginInvoke(3000,out threadId, null, null);  Thread.Sleep(0);  Console.WriteLine("主線程線程 {0} 正在運行.",Thread.CurrentThread.ManagedThreadId)  //會阻塞線程,直到后臺線程執行完畢之后,才會往下執行  result.AsyncWaitHandle.WaitOne();  Console.WriteLine("主程序在做一些事情!??!");  //獲取異步執行的結果  string returnValue = caller.EndInvoke(out threadId, result);  //釋放資源  result.AsyncWaitHandle.Close();  Console.WriteLine("主程序結束--------------------");  Console.Read(); }}public class AsyncDemo{ //供后臺線程執行的方法 public string TestMethod(int callDuration, out int threadId) {  Console.WriteLine("測試方法開始執行.");  Thread.Sleep(callDuration);  threadId = Thread.CurrentThread.ManagedThreadId;  return String.Format("測試方法執行的時間 {0}.", callDuration.ToString()); }}public delegate string AsyncMethodCaller(int callDuration, out int threadId);

關鍵步驟就是紅色字體的部分,運行結果:

Thread,Task,Async/Await,IAsyncResult

和Task的用法差異不是很大!result.AsyncWaitHandle.WaitOne()就類似Task的Wait。

5.Parallel

最后說一下在循環中開啟多線程的簡單方法:

Stopwatch watch1 = new Stopwatch();watch1.Start();for (int i = 1; i <= 10; i++){ Console.Write(i + ","); Thread.Sleep(1000);}watch1.Stop();Console.WriteLine(watch1.Elapsed);Stopwatch watch2 = new Stopwatch();watch2.Start();//會調用線程池中的線程Parallel.For(1, 11, i =>{ Console.WriteLine(i + ",線程ID:" + Thread.CurrentThread.ManagedThreadId); Thread.Sleep(1000);});watch2.Stop();Console.WriteLine(watch2.Elapsed);

運行結果:

Thread,Task,Async/Await,IAsyncResult

循環List<T>:

List<int> list = new List<int>() { 1, 2, 3, 4, 5, 6, 6, 7, 8, 9 };Parallel.ForEach<int>(list, n =>{ Console.WriteLine(n); Thread.Sleep(1000);});

執行Action[]數組里面的方法:

Action[] actions = new Action[] {  new Action(()=>{  Console.WriteLine("方法1"); }), new Action(()=>{  Console.WriteLine("方法2"); })};Parallel.Invoke(actions);

以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持VEVB武林網!


注:相關教程知識閱讀請移步到c#教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产福利精品视频| 国产精品成人一区二区三区吃奶| 91精品久久久久| 日本国产高清不卡| 欧美第一黄网免费网站| 国产男人精品视频| 日韩成人在线视频网站| 国产精品第三页| 国产丝袜一区视频在线观看| 国产精品777| 国产中文字幕日韩| 亚洲精品美女在线| 国产精品久久久久7777婷婷| 亚洲网站在线播放| 这里只有精品在线观看| 国产女人18毛片水18精品| 欧美国产在线电影| 亚洲成人黄色在线| 日韩欧美极品在线观看| 欧美成人在线免费视频| 姬川优奈aav一区二区| 久久精品国产综合| 日韩欧美成人免费视频| 欧美午夜电影在线| 欧美日韩国产91| 国产精品久久久久久久久久小说| 日韩av免费观影| 91国产视频在线播放| 久久久亚洲福利精品午夜| 538国产精品视频一区二区| 米奇精品一区二区三区在线观看| 久久久999精品免费| 91精品国产综合久久久久久蜜臀| 色yeye香蕉凹凸一区二区av| 国产激情综合五月久久| 日韩中文字幕在线观看| 国产成人亚洲综合| 777777777亚洲妇女| 久久久精品国产一区二区| 国模精品视频一区二区三区| 国产精品亚洲一区二区三区| 亚洲自拍高清视频网站| 7777免费精品视频| 91久久夜色精品国产网站| 亚洲男人天堂手机在线| 岛国精品视频在线播放| 亚洲一级一级97网| 亚洲欧美日韩精品久久奇米色影视| 7777kkkk成人观看| 97国产在线观看| 中文欧美日本在线资源| 日韩中文在线不卡| 国产亚洲精品一区二区| 国产成人精品视| 国产成人久久久精品一区| 日韩资源在线观看| 美女撒尿一区二区三区| 欧美成人四级hd版| 91亚洲va在线va天堂va国| 欧美中在线观看| 久久久久久久久爱| 亚洲天堂av高清| 日韩欧美黄色动漫| 欧美成人高清视频| 热99在线视频| 中文在线资源观看视频网站免费不卡| 777777777亚洲妇女| 亚洲天堂av图片| 国产精品视频网站| 欧美性感美女h网站在线观看免费| 欧美日韩精品在线观看| 日韩av在线电影网| 91欧美精品成人综合在线观看| 国产精品久久不能| 亚洲成人av在线播放| 亚洲人精品午夜在线观看| 精品中文字幕在线观看| 久久这里有精品视频| 色综合视频一区中文字幕| 久久久久久久久久久免费精品| 亚洲欧美日韩一区二区三区在线| 色综合男人天堂| 日韩视频免费大全中文字幕| 亚洲美女视频网| 欧洲精品久久久| 日韩精品视频在线播放| 欧美日韩另类在线| 热99精品只有里视频精品| 久久久视频在线| 欧美成人免费大片| 日韩高清电影免费观看完整版| 中文字幕免费精品一区高清| 久久久精品久久久久| 久久这里只有精品视频首页| 一区二区三区在线播放欧美| 国产成人精品视频| 国产亚洲日本欧美韩国| 久久精品视频在线观看| 成人免费福利视频| 日韩精品在线观看网站| 亚洲欧美一区二区三区久久| 九九久久久久久久久激情| 国产精品揄拍500视频| 国产精品久久久久久久久免费| 国产三级精品网站| 亚洲精品国产综合区久久久久久久| 欧美性极品少妇精品网站| 国产成人高潮免费观看精品| 国产脚交av在线一区二区| 亚洲欧美日韩国产精品| 国产日韩av在线播放| 久久精品国产欧美亚洲人人爽| 欧美性xxxxx极品| 国产成人91久久精品| 在线视频中文亚洲| 自拍偷拍亚洲精品| 久久福利网址导航| 北条麻妃一区二区在线观看| 国产午夜精品视频| 在线免费观看羞羞视频一区二区| 国产精品老女人视频| 亚洲国产精品嫩草影院久久| 黑人巨大精品欧美一区二区免费| 国产亚洲精品成人av久久ww| 亚洲国内精品在线| 久久精品成人一区二区三区| 午夜精品视频网站| 国产精品成人一区二区三区吃奶| 亚洲精品xxxx| 动漫精品一区二区| 影音先锋欧美在线资源| 成人看片人aa| 91深夜福利视频| 久久久久久亚洲| 成人www视频在线观看| 日本最新高清不卡中文字幕| 亚洲欧美日韩中文在线| 亚洲国产精品99久久| 色偷偷亚洲男人天堂| 国产成人福利网站| 亚洲一区二区三区在线视频| 91系列在线观看| 国产精品日日摸夜夜添夜夜av| 亚洲自拍偷拍视频| 久久综合久久美利坚合众国| 欧美精品在线播放| 黄色一区二区三区| 亚洲毛茸茸少妇高潮呻吟| 97视频在线观看播放| 亚洲三级 欧美三级| 久久久久99精品久久久久| 国产精品极品尤物在线观看| 国产精品视频最多的网站| 国产盗摄xxxx视频xxx69| 国产在线999| 亚洲在线免费看| 亚洲欧美制服另类日韩| 2018日韩中文字幕| 日韩中文字幕欧美| 91超碰caoporn97人人| 日韩经典中文字幕| 亚洲欧美综合精品久久成人| 亚洲国产精品大全| 欧美大片在线影院|