最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

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的參數(shù)是一個(gè)Action委托,并且不出意外的話,委托里面總會(huì)有一個(gè)地方調(diào)用一個(gè)MoveNext()方法,它推動(dòng)狀態(tài)機(jī)到達(dá)下一個(gè)狀態(tài),然后執(zhí)行下一個(gè)狀態(tài)需要執(zhí)行的代碼。
  那么,知道這個(gè)有什么用呢?第一,它是你充分了解async/await這套機(jī)制的基礎(chǔ),包括與之相關(guān)的同步上下文、執(zhí)行上下文、死鎖問(wèn)題等,第二,它可以實(shí)現(xiàn)一些特殊的功能。
  從上一篇我們知道,OnCompleted中的contination的主要目的是推動(dòng)狀態(tài)機(jī)的執(zhí)行,也就是推動(dòng)異步方法中await后面部分的代碼執(zhí)行。從這里看出,continuation的執(zhí)行是受我們控制的,因此我們可以直接執(zhí)行它,或是等待某個(gè)條件成熟然后執(zhí)行它,我們可以把它放到線程池執(zhí)行,也可以單獨(dú)起一個(gè)線程執(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("調(diào)用GetResult以獲取結(jié)果");
    }
    public void OnCompleted(Action continuation)
    {
        Console.WriteLine("調(diào)用OnCompleted,把Await后面部分要執(zhí)行的代碼傳遞過(guò)來(lái)(傳遞MoveNext,以推動(dòng)狀態(tài)機(jī)流轉(zhuǎn))");
        ThreadPool.QueueUserWorkItem(state =>
        {
            Console.WriteLine("開(kāi)始執(zhí)行Await后面部分的代碼");
            continuation();
            Console.WriteLine("后面部分的代碼執(zhí)行完畢");
        });
        Console.WriteLine("返回調(diào)用線程");
    }

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

  這是一個(gè)控制臺(tái)程序,輸出結(jié)果如下。

是否是線程池線程?False
獲得Awaiter
調(diào)用OnCompleted,把Await后面部分要執(zhí)行的代碼傳遞過(guò)來(lái)(傳遞MoveNext,以推動(dòng)狀態(tài)機(jī)流轉(zhuǎn))
返回調(diào)用線程
開(kāi)始執(zhí)行Await后面部分的代碼
調(diào)用GetResult以獲取結(jié)果
是否是線程池線程?True
后面部分的代碼執(zhí)行完畢

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

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

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

  輸出如下

是否是線程池線程?False
獲得Awaiter
調(diào)用OnCompleted,把Await后面部分要執(zhí)行的代碼傳遞過(guò)來(lái)(傳遞MoveNext,以推動(dòng)狀態(tài)機(jī)流轉(zhuǎn))
返回調(diào)用線程
開(kāi)始執(zhí)行Await后面部分的代碼
調(diào)用GetResult以獲取結(jié)果
結(jié)果是1
是否是線程池線程?True
后面部分的代碼執(zhí)行完畢

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

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

相關(guān)文章

  • c#中xml文檔注釋編譯dll引用到其它項(xiàng)目示例

    c#中xml文檔注釋編譯dll引用到其它項(xiàng)目示例

    這篇文章主要介紹了c#中xml文檔注釋編譯dll引用到其它項(xiàng)目示例,需要的朋友可以參考下
    2014-02-02
  • C#如何調(diào)用MFC 窗口 DLL

    C#如何調(diào)用MFC 窗口 DLL

    這篇文章主要介紹了C#如何調(diào)用MFC 窗口 DLL,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • C#中Foreach循環(huán)遍歷的本質(zhì)與枚舉器詳解

    C#中Foreach循環(huán)遍歷的本質(zhì)與枚舉器詳解

    這篇文章主要給大家介紹了關(guān)于C#中Foreach循環(huán)遍歷本質(zhì)與枚舉器的相關(guān)資料,foreach循環(huán)用于列舉出集合中所有的元素,foreach語(yǔ)句中的表達(dá)式由關(guān)鍵字in隔開(kāi)的兩個(gè)項(xiàng)組成,本文通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-08-08
  • 詳解Unity中的ShaderGraph入門(mén)使用教程

    詳解Unity中的ShaderGraph入門(mén)使用教程

    Unity2018版本之后推出了一個(gè)可編程渲染管線工具ShaderGraph,讓我們可以通過(guò)可視化界面拖拽來(lái)實(shí)現(xiàn)著色器的創(chuàng)建和編輯,今天重點(diǎn)給大家介紹Unity中的ShaderGraph入門(mén)使用教程,需要的朋友參考下吧
    2021-07-07
  • C#短消息提示窗口位置及窗口大小詳解

    C#短消息提示窗口位置及窗口大小詳解

    在我們的生活中無(wú)論是使用QQ,360安全衛(wèi)士等軟件的過(guò)程中,經(jīng)常會(huì)遇到從右下方的托盤(pán)處彈出一個(gè)消息提示窗,比如新聞,產(chǎn)品更新等內(nèi)容,下面這篇文章主要給大家介紹了關(guān)于C#短消息提示窗口位置及窗口大小的相關(guān)資料,需要的朋友可以參考下
    2022-12-12
  • C#?form-data上傳圖片流到遠(yuǎn)程服務(wù)器的詳細(xì)代碼

    C#?form-data上傳圖片流到遠(yuǎn)程服務(wù)器的詳細(xì)代碼

    這篇文章主要介紹了C#?form-data上傳圖片流到遠(yuǎn)程服務(wù)器的詳細(xì)代碼,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08
  • 淺談C#設(shè)計(jì)模式之代理模式

    淺談C#設(shè)計(jì)模式之代理模式

    這篇文章主要介紹了淺談C#設(shè)計(jì)模式之代理模式,需要的朋友可以參考下
    2014-12-12
  • C#實(shí)現(xiàn)啟用與禁用本地網(wǎng)絡(luò)的方式小結(jié)【3種方式】

    C#實(shí)現(xiàn)啟用與禁用本地網(wǎng)絡(luò)的方式小結(jié)【3種方式】

    這篇文章主要介紹了C#實(shí)現(xiàn)啟用與禁用本地網(wǎng)絡(luò)的方式,結(jié)合實(shí)例形式總結(jié)分析了使用Hnetcfg.dll、Shell32.dll及setupapi.dll三種啟用與禁用本地網(wǎng)絡(luò)的操作方法,需要的朋友可以參考下
    2016-07-07
  • C#遠(yuǎn)程發(fā)送和接收數(shù)據(jù)流生成圖片的方法

    C#遠(yuǎn)程發(fā)送和接收數(shù)據(jù)流生成圖片的方法

    這篇文章主要介紹了C#遠(yuǎn)程發(fā)送和接收數(shù)據(jù)流生成圖片的方法,涉及C#通過(guò)數(shù)據(jù)流傳輸圖片的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-07-07
  • C#網(wǎng)絡(luò)編程之Socket編程

    C#網(wǎng)絡(luò)編程之Socket編程

    本文詳細(xì)講解了C#網(wǎng)絡(luò)編程的Socket編程,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-02-02

最新評(píng)論

新闻| 加查县| 江安县| 崇明县| 永修县| 石棉县| 石楼县| 遂平县| 梁河县| 南京市| 阳山县| 东港市| 福海县| 垣曲县| 湄潭县| 镇江市| 承德县| 兴山县| 天祝| 泌阳县| 犍为县| 宁津县| 顺义区| 邹城市| 山丹县| 静乐县| 卓资县| 安阳县| 霍城县| 阜城县| 望奎县| 宿州市| 郁南县| 奉新县| 怀远县| 梁山县| 峨边| 新平| 沙雅县| 商水县| 聊城市|