天天看點

C# 中的Async 和 Await 的用法詳解寫在前面執行個體講解最後

文章目錄

  • 寫在前面
  • 執行個體講解
    • 第一個例子
    • 第二個例子
    • 第三個例子
  • 最後

衆所周知C#提供Async和Await關鍵字來實作異步程式設計。在本文中,我們将共同探讨并介紹什麼是Async 和 Await,以及如何在C#中使用Async 和 Await。

同樣本文的内容也大多是翻譯的,隻不過加上了自己的了解進行了相關知識點的補充,如果你認為自己的英文水準還不錯,大可直接跳轉到文章末尾檢視原文連結進行閱讀。

寫在前面

自從C# 5.0時代引入async和await關鍵字後,異步程式設計就變得流行起來。尤其在現在的.NET Core時代,如果你的代碼中沒有出現async或者await關鍵字,都會讓人感覺到很奇怪。

想象一下當我們在處理UI和按鈕單擊時,我們需要運作一個長時間運作的方法,比如讀取一個大檔案或其他需要很長時間的任務,在這種情況下,整個應用程式必須等待這個長時間運作的任務完成才算完成整個任務。

換句話說,如果同步應用程式中的任何程序被阻塞,則整個應用程式将被阻塞,我們的應用程式将停止響應,直到整個任務完成。

在這種情況下,異步程式設計将非常有用。通過使用異步程式設計,應用程式可以繼續進行不依賴于整個任務完成的其他工作。

在Async 和 await關鍵字的幫助下,使得異步程式設計變得很簡單,而且我們将獲得傳統異步程式設計的所有好處。

執行個體講解

假設我們分别使用了兩種方法,即Method 1和Method 2,這兩種方法不互相依賴,而Method 1需要很長時間才能完成它的任務。在同步程式設計中,它将執行第一個Method 1,并等待該方法的完成,然後執行Method 2。是以,這将是一個時間密集型的過程,即使這兩種方法并不互相依賴。

我們可以使用簡單的多線程程式設計并行運作所有方法,但是它會阻塞UI并等待完成所有任務。要解決這個問題,我們必須在傳統程式設計中編寫很多的代碼,但是現在我們有了Async 和 await關鍵字,那麼我們将通過書寫很少的并且簡潔的代碼來解決這個問題。

此外,我們還将看到更多的示例,如果任何第三個方法(如Method 3)都依賴于Method 1,那麼它将在Wait關鍵字的幫助下等待Method 1的完成。

Async 和 await是代碼标記,它标記代碼位置為任務完成後控件應該恢複的位置。

下面讓我們舉幾個例子來更好進行了解吧

C#中Async 和 await關鍵字的示例

我們将采用控制台應用程式進行示範。

第一個例子

在這個例子中,我們将采取兩個不互相依賴的方法。

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");
                // Do something
                Task.Delay(100).Wait();
            }
        });
    }


    public static void Method2()
    {
        for (int i = 0; i < 25; i++)
        {
            Console.WriteLine(" Method 2");
            // Do something
           Task.Delay(100).Wait();
        }
    }
}
           

在上面給出的代碼中,Method 1和Method 2不互相依賴,我們是從主方法調用的。

在這裡,我們可以清楚地看到,方法1和方法2并不是在等待對方完成。

輸出

C# 中的Async 和 Await 的用法詳解寫在前面執行個體講解最後

現在來看第二個例子,假設我們有Method 3,它依賴于Method 1

第二個例子

在本例中,Method 1将總長度作為整數值傳回,我們在Method 3中以長度的形式傳遞一個參數,它來自Method 1。

在這裡,在傳遞Method 3中的參數之前,我們必須使用AWAIT關鍵字,為此,我們必須使用調用方法中的async 關鍵字。

在控制台應用程式的Main方法中,因為不能使用async關鍵字而不能使用await 關鍵字,因為它會給出下面給出的錯誤。(但是如果你使用的是C#7.1及以上的方法是不會有問題的,因為C#7.1及以上的文法支援Mian方法前加async)

C# 中的Async 和 Await 的用法詳解寫在前面執行個體講解最後

我們将建立一個新的方法,作為CallMethod,在這個方法中,我們将調用我們的所有方法,分别為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需要一個參數,即Method 1的傳回類型。在這裡,await關鍵字對于等待Method 1任務的完成起着至關重要的作用。

輸出

C# 中的Async 和 Await 的用法詳解寫在前面執行個體講解最後

第三個例子

.NET Framework4.5中有一些支援API,Windows運作時包含支援異步程式設計的方法。

在Async 和 await關鍵字的幫助下,我們可以在實時項目中使用所有這些,以便更快地執行任務。

包含異步方法的API有HttpClient, SyndicationClient, StorageFile, StreamWriter, StreamReader, XmlReader, MediaCapture, BitmapEncoder, BitmapDecoder 等。

在本例中,我們将異步讀取大型文本檔案中的所有字元,并擷取所有字元的總長度。

class Program
{  ke
    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;
    }
}
           

在上面給出的代碼中,我們調用ReadFile方法來讀取文本檔案的内容,并擷取文本檔案中總字元的長度。

在sampleText.txt中,檔案包含了太多的字元,是以讀取所有字元需要很長時間。

在這裡,我們使用異步程式設計從檔案中讀取所有内容,是以它不會等待從這個方法獲得一個傳回值并執行其他代碼行,但是它必須等待下面給出的代碼行,因為我們使用的是等待關鍵字,我們将對下面給出的代碼行使用傳回值。

int length = await task;
Console.WriteLine(" Total length: " + length);  
           

随後,将按順序執行其他代碼行。

Console.WriteLine(" After work 1");  
Console.WriteLine(" After work 2");   
           

輸出

C# 中的Async 和 Await 的用法詳解寫在前面執行個體講解最後

最後

在這裡,我們必須了解非常重要的一點,如果我們沒有使用await 關鍵字,那麼該方法就作為一個同步方法。編譯器将向我們顯示警告,但不會顯示任何錯誤。

像上面這種簡單的方式一樣,我們可以在C#代碼中使用async 和await關鍵字來愉快的進行異步程式設計了。

最後的最後感謝大家的閱讀!

本文大部分内容翻譯自:https://www.c-sharpcorner.com/article/async-and-await-in-c-sharp/

作者:依樂祝

原文連結:https://www.cnblogs.com/yilezhu/p/10555849.html