亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C#異步編程由淺入深(三)之詳解Awaiter

 更新時間:2022年03月04日 10:01:43   作者:白煙染黑墨  
這篇文章主要介紹了C#異步編程由淺入深(三)之詳解Awaiter,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下

  上一篇末尾提到了Awaiter這個類型,上一篇說了,能await的對象,必須包含GetAwaiter()方法,不清楚的朋友可以看上篇文章。那么,Awaiter到底有什么特別之處呢?
  首先,從上篇文章我們知道,一個Awaiter必須實現INotifyCompletion接口,這個接口定義如下:

namespace System.Runtime.CompilerServices
{
    /// <summary>
    /// Represents an operation that will schedule continuations when the operation completes.
    /// </summary>
    public interface INotifyCompletion
    {
        /// <summary>Schedules the continuation action to be invoked when the instance completes.</summary>
        /// <param name="continuation">The action to invoke when the operation completes.</param>
        /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
        void OnCompleted(Action continuation);
    }
}

  除此之外還必須包含IsCompleted屬性和包含GetResult()方法。
  注意OnCompleted的參數是一個Action委托,并且不出意外的話,委托里面總會有一個地方調用一個MoveNext()方法,它推動狀態(tài)機到達下一個狀態(tài),然后執(zhí)行下一個狀態(tài)需要執(zhí)行的代碼。
  那么,知道這個有什么用呢?第一,它是你充分了解async/await這套機制的基礎,包括與之相關的同步上下文、執(zhí)行上下文、死鎖問題等,第二,它可以實現一些特殊的功能。
  從上一篇我們知道,OnCompleted中的contination的主要目的是推動狀態(tài)機的執(zhí)行,也就是推動異步方法中await后面部分的代碼執(zhí)行。從這里看出,continuation的執(zhí)行是受我們控制的,因此我們可以直接執(zhí)行它,或是等待某個條件成熟然后執(zhí)行它,我們可以把它放到線程池執(zhí)行,也可以單獨起一個線程執(zhí)行。譬如,我們可以讓await后面部分的代碼直接在線程池上執(zhí)行。

public static async Task AwaiterTest()
{
    Console.WriteLine($"是否是線程池線程?{Thread.CurrentThread.IsThreadPoolThread}");
    await default (SkipToThreadPoolAwaiter);
    Console.WriteLine($"是否是線程池線程?{Thread.CurrentThread.IsThreadPoolThread}");
}

static void Main(string[] args)
{
    _ = AwaiterTest();
    Console.ReadLine();
}

public struct SkipToThreadPoolAwaiter : INotifyCompletion
{
    public bool IsCompleted => false;
    public void GetResult() 
    {
        Console.WriteLine("調用GetResult以獲取結果");
    }
    public void OnCompleted(Action continuation)
    {
        Console.WriteLine("調用OnCompleted,把Await后面部分要執(zhí)行的代碼傳遞過來(傳遞MoveNext,以推動狀態(tài)機流轉)");
        ThreadPool.QueueUserWorkItem(state =>
        {
            Console.WriteLine("開始執(zhí)行Await后面部分的代碼");
            continuation();
            Console.WriteLine("后面部分的代碼執(zhí)行完畢");
        });
        Console.WriteLine("返回調用線程");
    }

    public SkipToThreadPoolAwaiter GetAwaiter()
    {
        Console.WriteLine("獲得Awaiter");
        return this;
    }
}

  這是一個控制臺程序,輸出結果如下。

是否是線程池線程?False
獲得Awaiter
調用OnCompleted,把Await后面部分要執(zhí)行的代碼傳遞過來(傳遞MoveNext,以推動狀態(tài)機流轉)
返回調用線程
開始執(zhí)行Await后面部分的代碼
調用GetResult以獲取結果
是否是線程池線程?True
后面部分的代碼執(zhí)行完畢

  特別注意一下,第五步說明可能有點疑惑,怎么第六步不是打印是否是線程池線程?原因是部分awaiter是有返回值的,在執(zhí)行await后面部分的代碼時,會首先調用GetResult()以獲取結果。這對編譯器改造異步方法來說是一個固定的模式(上篇文章沒有體現這一步)。
  把Awaiter改成有返回值嘗試。

public static async Task AwaiterTest()
{
    Console.WriteLine($"是否是線程池線程?{Thread.CurrentThread.IsThreadPoolThread}");
    var res = await default (SkipToThreadPoolAwaiter);
    Console.WriteLine($"結果是{res}");
}

static void Main(string[] args)
    _ = AwaiterTest();
    Console.ReadLine();
public struct SkipToThreadPoolAwaiter : INotifyCompletion
    public bool IsCompleted => false;
    public int GetResult() 
    {
        Console.WriteLine("調用GetResult以獲取結果");
        return 1;
    }
    public void OnCompleted(Action continuation)
        Console.WriteLine("調用OnCompleted,把Await后面部分要執(zhí)行的代碼傳遞過來(傳遞MoveNext,以推動狀態(tài)機流轉)");
        ThreadPool.QueueUserWorkItem(state =>
        {
            Console.WriteLine("開始執(zhí)行Await后面部分的代碼");
            continuation();
            Console.WriteLine("后面部分的代碼執(zhí)行完畢");
        });
        Console.WriteLine("返回調用線程");
    public SkipToThreadPoolAwaiter GetAwaiter()
        Console.WriteLine("獲得Awaiter");
        return this;

  輸出如下

是否是線程池線程?False
獲得Awaiter
調用OnCompleted,把Await后面部分要執(zhí)行的代碼傳遞過來(傳遞MoveNext,以推動狀態(tài)機流轉)
返回調用線程
開始執(zhí)行Await后面部分的代碼
調用GetResult以獲取結果
結果是1
是否是線程池線程?True
后面部分的代碼執(zhí)行完畢

  對照前面的文章來看,相信你應該有所得,能解決你部分的疑惑。前面說到,我們可以控制continuation的執(zhí)行,那如果當前線程有同步上下文(SychronizationContext),我們是不是可以放到同步上下文中執(zhí)行?TaskAwaiter是會這么做的,如果你不想它使用同步上下文,你可以在Task實例上調用ConfigureAwait(false),它表面后面部分的代碼將不會使用同步上下文執(zhí)行。
  另外說一下Task.Yield()這個Awaiter,他的行為是捕捉同步上下文,如果有,則會放到同步上下文中執(zhí)行,如果沒有,則會放到線程池中執(zhí)行。在窗體程序中,有時候你打開一個模態(tài)對話框,會導致主窗體部分的動畫沒有反應,在模態(tài)對話框關閉之后,才會反應。原因是模態(tài)對話框阻塞了主窗體的消息循環(huán),也就是阻塞了主線程,如果想讓動畫先完成,然后再打開模態(tài)對話框,則可以在打開模態(tài)對話框之前,Await Task.Yield(),這也對應了它的意思,讓渡之意。
  后面文章還會說明同步上下文具體是什么、異步代碼中使用同步代碼會導致死鎖的本質原因、如何實現類似Task的類,并且怎么與Async/await這套機制搭配使用等知識。
  覺得有收獲的不妨點個贊,有支持才有動力寫出更好的文章。

到此這篇關于C#異步編程由淺入深(三)細說Awaiter的文章就介紹到這了,更多相關C#異步編程Awaiter內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • unity 如何獲取Text組件里text內容的長度

    unity 如何獲取Text組件里text內容的長度

    這篇文章主要介紹了unity 獲取Text組件里text內容的長度操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • C# ref and out的使用小結

    C# ref and out的使用小結

    這篇文章主要介紹了C# ref and out的使用小結,幫助大家更好的理解和學習使用c#,感興趣的朋友可以了解下
    2021-03-03
  • C# 中楊輝三角的實現

    C# 中楊輝三角的實現

    這篇文章主要介紹了C# 中楊輝三角的實現的相關資料,希望通過本文大家能掌握這部分內容,需要的朋友可以參考下
    2017-09-09
  • 基于C#模擬實現回合制游戲

    基于C#模擬實現回合制游戲

    這篇文章主要介紹了通過C#模擬實現回合制游戲,文中的示例代碼講解詳細,對我們的學習和工作有一定的幫助,感興趣的可以跟隨小編一起學習一下
    2021-12-12
  • C#中Socket與Unity相結合示例代碼

    C#中Socket與Unity相結合示例代碼

    這篇文章主要給大家介紹了關于C#中Socket與Unity相結合的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考借鑒,下面隨著小編來一起學習學習吧。
    2017-10-10
  • C# XML文件操作之相機參數保存和讀取

    C# XML文件操作之相機參數保存和讀取

    XML是可擴展標記語言是一種數據語言,它將數據以一種簡單的文本格式存儲,可以被人類和幾乎任何計算機理解。本文將利用C#實現相機參數讀取并保存至XML文件,感興趣的可以學習一下
    2022-11-11
  • 詳解C#通過反射獲取對象的幾種方式比較

    詳解C#通過反射獲取對象的幾種方式比較

    本文主要介紹了C#通過反射獲取對象的幾種方式比較,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-06-06
  • C#如何用ThoughtWorks生成二維碼

    C#如何用ThoughtWorks生成二維碼

    這篇文章主要介紹了C#如何用ThoughtWorks生成二維碼,文中講解非常細致,幫助大家更好的理解和學習,感興趣的朋友可以了解下
    2020-08-08
  • 使用C#?11的靜態(tài)接口方法改進?面向約定?的設計方法

    使用C#?11的靜態(tài)接口方法改進?面向約定?的設計方法

    我們知道接口是針對契約的定義,但是一直以來它只能定義一組“實例”的契約,而不能定義類型的契約,因為定義在接口中的方法只能是實例方,這篇文章主要介紹了使用C#?11的靜態(tài)接口方法改進面向約定?的設計,需要的朋友可以參考下
    2022-12-12
  • C# Process調用外部程序的實現

    C# Process調用外部程序的實現

    這篇文章主要介紹了C# Process調用外部程序的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-02-02

最新評論