C#多線程系列之a(chǎn)sync和await用法詳解_第1頁
C#多線程系列之a(chǎn)sync和await用法詳解_第2頁
C#多線程系列之a(chǎn)sync和await用法詳解_第3頁
C#多線程系列之a(chǎn)sync和await用法詳解_第4頁
C#多線程系列之a(chǎn)sync和await用法詳解_第5頁
已閱讀5頁,還剩7頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第C#多線程系列之a(chǎn)sync和await用法詳解目錄async和awaitasyncawait從以往知識推導(dǎo)創(chuàng)建異步任務(wù)創(chuàng)建異步任務(wù)并返回Task異步改同步說說awaitTask說說asyncTaskTResult同步異步?Task封裝異步任務(wù)關(guān)于跳到await變異步為什么出現(xiàn)一層層的await

async和await

async

微軟文檔:使用async修飾符可將方法、lambda表達式或匿名方法指定為異步。

使用async修飾的方法,稱為異步方法。

例如:

為了命名規(guī)范,使用async修飾的方法,需要在方法名稱后面加上Async。

publicasyncTaskintTestAsync()

//....

}

Lambda:

staticvoidMain()

Threadthread=newThread(async()=

awaitTask.Delay(0);

publicstaticasyncTaskintTestAsync()=666;

await

微軟文檔:await運算符暫停對其所屬的async方法的求值,直到其操作數(shù)表示的異步操作完成。

異步操作完成后,await運算符將返回操作的結(jié)果(如果有)。

好的,到此為止,async和await,在官方文檔中的說明,就這么多。

從以往知識推導(dǎo)

這里,你會跟筆者從以往文章中學(xué)習(xí)到的知識,去推導(dǎo),去理解async和await這兩個關(guān)鍵字是如何使用的,又應(yīng)該怎么合理使用。

這里我們不參考文檔和書籍的資料,不要看文檔和書籍中的示例,我們要一步步來從任務(wù)(Task)中的同步異步開始,慢慢摸索。去分析async和await兩個關(guān)鍵字給我們的異步編程帶來了什么樣的便利。

創(chuàng)建異步任務(wù)

場景:周六日放假了,可以打王者(一種游戲),但是昨天的衣服還沒有洗;于是用洗衣機洗衣服,清洗期間,開一局王者(一種游戲)。

我們可以編寫一個方法如下:

staticvoidMain()

Console.WriteLine("準(zhǔn)備洗衣服");

//創(chuàng)建一個洗衣服的任務(wù)

Taskinttask=newTaskint(()=

//模擬洗衣服的時間

inttime=newRandom().Next(2,6);

Thread.Sleep(TimeSpan.FromSeconds(time));

returntime;

Console.WriteLine("開始洗衣服");

//讓洗衣機洗衣服

task.Start();

Console.WriteLine("我去打王者,讓洗衣機洗衣服");

//打王者

Thread.Sleep(TimeSpan.FromSeconds(4));

Console.WriteLine("打完王者了,衣服洗完了嘛?");

Console.WriteLine(task.IsCompleted);

if(task.IsCompleted)

Console.WriteLine("洗衣服花的時間:"+task.Result);

else

Console.WriteLine("在等洗衣機洗完衣服");

task.Wait();

Console.WriteLine("洗衣服花的時間:"+task.Result);

Console.WriteLine("洗完了,撈出衣服,曬衣服,繼續(xù)打王者去");

}

創(chuàng)建異步任務(wù)并返回Task

上面的示例,雖然說,異步完成了一個任務(wù),但是這樣,將代碼都放到Main,可讀性十分差,還要其它什么規(guī)范之類的,不允許我們寫這樣的垃圾代碼。于是我們將洗衣服這個任務(wù),封裝到一個方法中,然后返回Task即可。

在Program類中,加入如下一個方法,這個方法用于執(zhí)行異步任務(wù),并且返回Task對象。

///summary

///執(zhí)行一個任務(wù)

////summary

///returns/returns

publicstaticTaskintTestAsync()

Taskinttask=newTaskint(()=

//模擬洗衣服的時間

inttime=newRandom().Next(2,6);

Thread.Sleep(TimeSpan.FromSeconds(time));

returntime;

task.Start();

returntask;

}

Main方法中,改成

staticvoidMain()

Console.WriteLine("準(zhǔn)備洗衣服");

//創(chuàng)建一個洗衣服的任務(wù)

Taskinttask=TestAsync();

......

但是,兩者差別還是不大。

異步改同步

我們創(chuàng)建了異步方法,去執(zhí)行一個洗衣服的任務(wù);當(dāng)打完游戲后,需要檢查任務(wù)是否完成,然后才能進行下一步操作,這時候就出現(xiàn)了同步。為了保持同步和獲得執(zhí)行結(jié)果,我們使用了.Wait()、.Result。

這里我們嘗試將上面的操作轉(zhuǎn)為同步,并且獲得執(zhí)行結(jié)果。

classProgram

staticvoidMain()

inttime=Test();

//......

///summary

///執(zhí)行一個任務(wù)

////summary

///returns/returns

publicstaticintTest()

Taskinttask=newTaskint(()=

//模擬洗衣服的時間

inttime=newRandom().Next(2,6);

Thread.Sleep(TimeSpan.FromSeconds(time));

returntime;

task.Start();

returntask.Result;

}

說說awaitTask

Task和TaskTResult,前者是一個沒有返回結(jié)果的任務(wù),后者是有返回結(jié)果的任務(wù)。前面的文章中已經(jīng)使用過大量的示例,這里我們使用await,去完成一些完全相同的功能。

Task:

publicstaticvoidT1()

Tasktask=newTask(()={});

task.Wait();

}

publicstaticasyncvoidT2()

Tasktask=newTask(()={});

awaittask;

}

說明,await可以讓程序等待任務(wù)完成。

TaskTResult:

publicvoidT3()

//獲取Task任務(wù)對象,后面的邏輯過程可以弄成異步

Taskinttask=TestAsync();

//任務(wù)是異步在執(zhí)行,我不理會他

//這里可以處理其它事情,處理完畢后,再獲取執(zhí)行結(jié)果

//這就是異步

Console.WriteLine(task.Result);

}

publicasyncvoidT4()

//使用await關(guān)鍵字,代表等待執(zhí)行完成,同步

inttime=awaitTestAsync();

Console.WriteLine(time);

}

說明:await可以讓程序等待任務(wù)執(zhí)行完成,并且獲得執(zhí)行結(jié)果。

看到?jīng)]有。。。await關(guān)鍵字,作用是讓你等,是同步的,壓根不是直接讓你的任務(wù)變成異步后臺執(zhí)行的。

那為啥提到async、await,都是說跟異步有關(guān)?不急,后面解釋。

說說asyncTaskTResult

asyncTaskTResult修飾一個方法,那么這個方法要返回awaitTaskTResult的結(jié)果。

兩種同步方式示例對比:

publicstaticintTest()

Taskinttask=newTaskint(()=

//模擬洗衣服的時間

inttime=newRandom().Next(2,6);

Thread.Sleep(TimeSpan.FromSeconds(time));

returntime;

task.Start();

returntask.Result;

}

publicstaticasyncTaskintTestAsync()

Taskinttask=newTaskint(()=

//模擬洗衣服的時間

inttime=newRandom().Next(2,6);

Thread.Sleep(TimeSpan.FromSeconds(time));

returntime;

task.Start();

inttime=awaittask;

returntime;

}

同步異步?

問:async和await不是跟異步方法有關(guān)嘛,為啥前面的示例使用了await,全部變成同步了?

問:使用async和await的方法,執(zhí)行過程到底是同步還是異步?

答:同步異步都行,要同步還是異步,全掌握在你的手上。

你使用await去調(diào)用一個異步方法,其執(zhí)行過程就是同步。你獲取異步方法返回的Task,就是異步。

最近筆者收到一些提問,有些讀者,使用async和await去編寫業(yè)務(wù),想著是異步,可以提升性能,實際結(jié)果還是同步,性能一點沒有提升。通過下面的示例,你會馬上理解應(yīng)該怎么用。

首先,在不使用async和await關(guān)鍵字的情況下,我們來編寫兩個方法,分別實現(xiàn)同步和異步的功能,兩個方法執(zhí)行的結(jié)果是一致的。

///summary

///同步

////summary

///returns/returns

publicstaticintTest()

Taskinttask=newTaskint(()=

return666;

task.Start();

returntask.Result;

///summary

///異步

////summary

///returns/returns

publicstaticTaskintTestAsync()

Taskinttask=newTaskint(()=

return666;

task.Start();

returntask;

}

能不能將兩個方法合并在一起呢?想同步就同步,想異步就異步,這樣就不需要寫兩個方法了!

是可以的!通過async和await關(guān)鍵字,可以輕松實現(xiàn)!

合并后,代碼如下:

///summary

///可異步可同步

////summary

///returns/returns

publicstaticasyncTaskintTestAsync()

Taskinttask=newTaskint(()=

return666;

task.Start();

returnawaittask;

}

合并后,我們又應(yīng)該怎么在調(diào)用的時候,實現(xiàn)同步和異步呢?

筆者這里給出兩個示例:

//await使得任務(wù)同步

publicasyncvoidT1()

//使用await關(guān)鍵字,代表等待執(zhí)行完成,同步

inttime=awaitTestAsync();

Console.WriteLine(time);

//直接獲得返回的Task,實現(xiàn)異步

publicvoidT2()

//獲取Task任務(wù)對象,后面的邏輯過程可以弄成異步

Taskinttask=TestAsync();

//任務(wù)是異步在執(zhí)行,我不理會他

//這里可以處理其它事情,處理完畢后,再獲取執(zhí)行結(jié)果

//這就是異步

Console.WriteLine(task.Result);

}

至此,理解為什么使用了async和await,執(zhí)行時還是同步了吧?

Task封裝異步任務(wù)

前面,我們都是使用了newTask()來創(chuàng)建任務(wù),而且微軟官網(wǎng)大多使用Task.Run()來編寫async和await的示例。

因此,我們可以修改前面的異步任務(wù),改成:

///summary

//

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論