淺談C#中的Async和Await的用法詳解
眾所周知C#提供Async和Await關(guān)鍵字來實現(xiàn)異步編程。在本文中,我們將共同探討并介紹什么是Async 和 Await,以及如何在C#中使用Async 和 Await。
同樣本文的內(nèi)容也大多是翻譯的,只不過加上了自己的理解進行了相關(guān)知識點的補充,如果你認為自己的英文水平還不錯,大可直接跳轉(zhuǎn)到文章末尾查看原文鏈接進行閱讀。
寫在前面
自從C# 5.0時代引入async和await關(guān)鍵字后,異步編程就變得流行起來。尤其在現(xiàn)在的.NET Core時代,如果你的代碼中沒有出現(xiàn)async或者await關(guān)鍵字,都會讓人感覺到很奇怪。
想象一下當我們在處理UI和按鈕單擊時,我們需要運行一個長時間運行的方法,比如讀取一個大文件或其他需要很長時間的任務(wù),在這種情況下,整個應(yīng)用程序必須等待這個長時間運行的任務(wù)完成才算完成整個任務(wù)。
換句話說,如果同步應(yīng)用程序中的任何進程被阻塞,則整個應(yīng)用程序?qū)⒈蛔枞?,我們的?yīng)用程序?qū)⑼V鬼憫?yīng),直到整個任務(wù)完成。
在這種情況下,異步編程將非常有用。通過使用異步編程,應(yīng)用程序可以繼續(xù)進行不依賴于整個任務(wù)完成的其他工作。
在Async 和 await關(guān)鍵字的幫助下,使得異步編程變得很簡單,而且我們將獲得傳統(tǒng)異步編程的所有好處。
實例講解
假設(shè)我們分別使用了兩種方法,即Method 1和Method 2,這兩種方法不相互依賴,而Method 1需要很長時間才能完成它的任務(wù)。在同步編程中,它將執(zhí)行第一個Method 1,并等待該方法的完成,然后執(zhí)行Method 2。因此,這將是一個時間密集型的過程,即使這兩種方法并不相互依賴。
我們可以使用簡單的多線程編程并行運行所有方法,但是它會阻塞UI并等待完成所有任務(wù)。要解決這個問題,我們必須在傳統(tǒng)編程中編寫很多的代碼,但是現(xiàn)在我們有了Async 和 await關(guān)鍵字,那么我們將通過書寫很少的并且簡潔的代碼來解決這個問題。
此外,我們還將看到更多的示例,如果任何第三個方法(如Method 3)都依賴于Method 1,那么它將在Wait關(guān)鍵字的幫助下等待Method 1的完成。
Async 和 await是代碼標記,它標記代碼位置為任務(wù)完成后控件應(yīng)該恢復的位置。
下面讓我們舉幾個例子來更好進行理解吧
C#中Async 和 await關(guān)鍵字的示例
我們將采用控制臺應(yīng)用程序進行演示。
第一個例子
在這個例子中,我們將采取兩個不相互依賴的方法。
class Program
{
static void Main(string[] args)
{
Method1();
Method2();
Console.ReadKey();
}
public static async Task Method1()
{
await Task.Run(() =>
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine(" Method 1");
}
});
}
public static void Method2()
{
for (int i = 0; i < 25; i++)
{
Console.WriteLine(" Method 2");
}
}
}
在上面給出的代碼中,Method 1和Method 2不相互依賴,我們是從主方法調(diào)用的。
在這里,我們可以清楚地看到,方法1和方法2并不是在等待對方完成。
輸出
現(xiàn)在來看第二個例子,假設(shè)我們有Method 3,它依賴于Method 1
第二個例子
在本例中,Method 1將總長度作為整數(shù)值返回,我們在Method 3中以長度的形式傳遞一個參數(shù),它來自Method 1。
在這里,在傳遞Method 3中的參數(shù)之前,我們必須使用AWAIT關(guān)鍵字,為此,我們必須使用調(diào)用方法中的async 關(guān)鍵字。
在控制臺應(yīng)用程序的Main方法中,因為不能使用async關(guān)鍵字而不能使用await 關(guān)鍵字,因為它會給出下面給出的錯誤。(但是如果你使用的是C#7.1及以上的方法是不會有問題的,因為C#7.1及以上的語法支持Mian方法前加async)
我們將創(chuàng)建一個新的方法,作為CallMethod,在這個方法中,我們將調(diào)用我們的所有方法,分別為Method 1、Method 2和Method 3。
class Program
{
static void Main(string[] args)
{
callMethod();
Console.ReadKey();
}
public static async void callMethod()
{
Task<int> task = Method1();
Method2();
int count = await task;
Method3(count);
}
public static async Task<int> Method1()
{
int count = 0;
await Task.Run(() =>
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine(" Method 1");
count += 1;
}
});
return count;
}
public static void Method2()
{
for (int i = 0; i < 25; i++)
{
Console.WriteLine(" Method 2");
}
}
public static void Method3(int count)
{
Console.WriteLine("Total count is " + count);
}
}
在上面給出的代碼中,Method 3需要一個參數(shù),即Method 1的返回類型。在這里,await關(guān)鍵字對于等待Method 1任務(wù)的完成起著至關(guān)重要的作用。
輸出
第三個例子
.NET Framework4.5中有一些支持API,Windows運行時包含支持異步編程的方法。
在Async 和 await關(guān)鍵字的幫助下,我們可以在實時項目中使用所有這些,以便更快地執(zhí)行任務(wù)。
包含異步方法的API有HttpClient, SyndicationClient, StorageFile, StreamWriter, StreamReader, XmlReader, MediaCapture, BitmapEncoder, BitmapDecoder 等。
在本例中,我們將異步讀取大型文本文件中的所有字符,并獲取所有字符的總長度。
class Program
{
static void Main()
{
Task task = new Task(CallMethod);
task.Start();
task.Wait();
Console.ReadLine();
}
static async void CallMethod()
{
string filePath = "E:\\sampleFile.txt";
Task<int> task = ReadFile(filePath);
Console.WriteLine(" Other Work 1");
Console.WriteLine(" Other Work 2");
Console.WriteLine(" Other Work 3");
int length = await task;
Console.WriteLine(" Total length: " + length);
Console.WriteLine(" After work 1");
Console.WriteLine(" After work 2");
}
static async Task<int> ReadFile(string file)
{
int length = 0;
Console.WriteLine(" File reading is stating");
using (StreamReader reader = new StreamReader(file))
{
// Reads all characters from the current position to the end of the stream asynchronously
// and returns them as one string.
string s = await reader.ReadToEndAsync();
length = s.Length;
}
Console.WriteLine(" File reading is completed");
return length;
}
}
在上面給出的代碼中,我們調(diào)用ReadFile方法來讀取文本文件的內(nèi)容,并獲取文本文件中總字符的長度。
在sampleText.txt中,文件包含了太多的字符,因此讀取所有字符需要很長時間。
在這里,我們使用異步編程從文件中讀取所有內(nèi)容,所以它不會等待從這個方法獲得一個返回值并執(zhí)行其他代碼行,但是它必須等待下面給出的代碼行,因為我們使用的是等待關(guān)鍵字,我們將對下面給出的代碼行使用返回值。
int length = await task;
Console.WriteLine(" Total length: " + length);
隨后,將按順序執(zhí)行其他代碼行。
Console.WriteLine(" After work 1");
Console.WriteLine(" After work 2");
輸出
最后
在這里,我們必須了解非常重要的一點,如果我們沒有使用await 關(guān)鍵字,那么該方法就作為一個同步方法。編譯器將向我們顯示警告,但不會顯示任何錯誤。
像上面這種簡單的方式一樣,我們可以在C#代碼中使用async 和await關(guān)鍵字來愉快的進行異步編程了。
最后的最后感謝大家的閱讀!希望對大家的學習有所幫助,也希望大家多多支持我們。
上一篇:C#開發(fā)windows服務(wù)實現(xiàn)自動從FTP服務(wù)器下載文件
欄 目:C#教程
下一篇:使用C# CefSharp Python采集某網(wǎng)站簡歷并且自動發(fā)送邀請短信的方法
本文地址:http://www.jygsgssxh.com/a1/C_jiaocheng/4825.html
您可能感興趣的文章
- 01-10C#中查找Dictionary中的重復值的方法
- 01-10C#將圖片存放到SQL SERVER數(shù)據(jù)庫中的方法
- 01-10關(guān)于nancy中的身份驗證
- 01-10C#中的事務(wù)用法實例分析
- 01-10C#實現(xiàn)讀取DataSet數(shù)據(jù)并顯示在ListView控件中的方法
- 01-10C#中的正則表達式介紹
- 01-10C#開發(fā)中的垃圾回收機制簡析
- 01-10C#語言中的修飾符匯總
- 01-10C#中的 == 和equals()區(qū)別淺析
- 01-10C#通過正則表達式實現(xiàn)提取網(wǎng)頁中的圖片


閱讀排行
本欄相關(guān)
- 01-10C#通過反射獲取當前工程中所有窗體并
- 01-10關(guān)于ASP網(wǎng)頁無法打開的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實現(xiàn)txt定位指定行完整實例
- 01-10WinForm實現(xiàn)仿視頻播放器左下角滾動新
- 01-10C#停止線程的方法
- 01-10C#實現(xiàn)清空回收站的方法
- 01-10C#通過重寫Panel改變邊框顏色與寬度的
- 01-10C#實現(xiàn)讀取注冊表監(jiān)控當前操作系統(tǒng)已
隨機閱讀
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 01-10C#中split用法實例總結(jié)
- 01-11ajax實現(xiàn)頁面的局部加載
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-10delphi制作wav文件的方法
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 04-02jquery與jsp,用jquery
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改


