主頁 > .NET開發 > async-await 執行緒分析

async-await 執行緒分析

2020-09-19 05:37:01 .NET開發

這里沒有執行緒

原文地址:https://blog.stephencleary.com/2013/11/there-is-no-thread.html

前言

我是在看 C#8.0 新特性異步流時在評論里看到這篇文章的,閱讀之后發現這篇文章干貨滿滿,作者解釋的非常清晰,里面的本質分析內容在《CLR via C#》一書中也有講到,更加加深了我的印象,遂在這里翻譯過來,以便加深自己的理解

正文

一個本質的事實就是純粹的異步是不會產生執行緒的

反對這個事實的人有很多,“不”,他們喊道:“如果我正在等待一個操作,那么這個執行緒就必須在執行等待!它可能是執行緒池執行緒,或者是一個作業系統(OS)執行緒,又或是其他設備驅動程式...”

無需理會他們,如果一個異步操作是純粹的(pure),那么就不會有執行緒的,

那些持懷疑態度的人,那我們就迎合他們罷,

我們將跟蹤一個異步操作一直到硬體,特別是 .net 部分和硬體部分,我們必須通過省略一些中間的細節來簡化描述,但是我們不能偏離事實真相,

通常寫一個異步操作(檔案,網路流,USB 介面等等),代碼如下:

private async void Button_Click(object sender, RoutedEventArgs s)
{
    byte[] data = https://www.cnblogs.com/ms27946/p/...
    await myDevice.WriteAsync(data, 0, data.Length);
}

我們已經知道在 await 的時候 UI 執行緒是不會阻塞的,那么問題來了:這里有沒有是其他執行緒在阻塞期間犧牲自己以至于讓 UI 執行緒存活呢?

那讓我們繼續往下深究

第一步:庫(比如進入到 BCL 庫源代碼),我們假使 WriteAsync 是通過 [http://msdn.microsoft.com/en-us/library/system.threading.overlapped.aspx](P/Invoke 在 .net 異步的標準實作) 來實作的,它是基于overllapped I/O 的,所有它在一個設備驅動程式的句柄上開始一個 Win32 overlapped 操作,

OVERLAPPED 是一個包含了用于異步輸入輸出的資訊的結構體;詳細解釋移步 https://en.wikipedia.org/wiki/Overlapped_I/O

作業系統然后就會轉向設備驅動程式并開始請求一個寫操作,它首先會構造一個表示寫請求的物件;它被稱為 I/O Request Packet(IRP),

設備驅動程式接受到 IRP 之后并向設備提交一個寫出資料的命令,如果這個設備支持直接記憶體訪問(DMA 全稱是 Direct Memory Access),這能夠像寫到緩沖區到暫存器一樣簡單,這就是設備驅動程式所做的一切;它把 IRP 標記為 "pending" (掛起) 并回傳給作業系統,

本質核心就在這里:設備驅動程式正在處理 IRP 時是不會允許阻塞的,也就是說如果 IRP 不能馬上完成,那么它必須要異步處理,甚至是同步 API 也是如此!在設備驅動程式級別,所有的請求(重要的)都是異步的,

這里參考了 Tomes 的知識,“無論I/O請求的型別如何,在內部,代表應用程式向驅動程式發出的I/O操作都是異步執行的”

在 IRP 掛起的時候,OS 回傳庫,庫回傳了一個未完成的任務給按鈕點擊事件,并暫停了 async 方法, UI 執行緒繼續執行,

我們跟著請求繼續往下走,現在到達了設備的物理層

現在寫操作正在進行,那么有多少執行緒正處理它呢?

沒有,

這里沒有設備驅動程式執行緒、OS 執行緒、庫(BCL)執行緒或者是執行緒池執行緒操作寫操作,這里沒有執行緒

現在我們來跟著從來自內核的相應回到最初的世界,

在開始寫請求之后的一段時間,設備完成了寫操作,它會以中斷的方式來通知 CPU,

設備驅動程式的中斷服務程式(ISR(Interrupt Service Routine) )回應中斷,這個中斷是 CPU 級別的事件,無論哪個執行緒正在運行都會臨時的搶占 CPU 的控制權,你可以認為 ISR 是在“借”當前正在運行的執行緒,但是我更傾向于 ISR 運行時的級別非常低,以至于不存在“執行緒”的概念,可以這么說,它們在所有執行緒之下進來的,

不管怎樣,ISR 正確寫完了,完了它會通知設備程式 “謝謝你的中斷” 并且進入 DPC(Deffered Procedure Call) 佇列(延遲程序呼叫)

當 CPU 被中斷干擾時,它將會到達 DPCs,DPCs 也會執行在一個很低的級別以至于說它是一個執行緒是不正確的;就像 ISRs,DPCs 直接在 CPU 上運行,在執行緒系統之下,

PDC 接受代表寫請求的 IRP 并且標記為 “已完成”,然而,這個“完成”狀態只存在于 OS 級別;行程有它自己的記憶體空間,它必須被通知,所以 OS 會入佇列一個特殊內核模式異步程序呼叫(APC)到擁有自己句柄的執行緒,

由于 BCL 庫使用了標準的 P/Invoke overlapped I/O 系統,它已經在 I/O Completion Port(IOCP)注冊句柄,它是執行緒池的一部分,所以借用 I/O 執行緒池執行緒來執行 APC,它會通知這些任務已經完成了,

這個任務已經捕捉了 UI 背景關系,所以它不會直接在執行緒池執行緒上恢復異步方法,而是它將該方法的延續排隊到 UI 背景關系中,并且 UI 執行緒將恢復執行那個方法,

所以我們看到,正當一個請求處理時這里是沒有執行緒的,當請求完成時,一些執行緒被借過去或者是被短暫的排隊,這項作業通常在 1 毫秒左右(例如 APC 運行在執行緒池執行緒)或 1 微妙左右(例如 ISR),但是這里沒有執行緒是阻塞的,僅僅只是等待請求完成,

現在,我們遵循的路徑是標準路徑,這是如此清晰簡單,這里有無數的變數,但是核心是不變的,

所以說 “這里必須有一個執行緒是在處理異步操作” 是不正確的,

釋懷吧,不要嘗試找到異步執行緒——這是不可能的,而是你應該去了解真相:

沒有執行緒

該篇文章的評論也是很精彩的,特別是討論將異步操作當作訊息處理那部分討論,建議也花時間看下

本文同步至:https://github.com/MarsonShine/MarsonShine.github.io/blob/master/mardown/async/There-IS-NO-Thread.md

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/79103.html

標籤:C#

上一篇:System.Data.SqlClient.SqlException: 列名 'TypeID' 無效。 列名 'Title' 無效。

下一篇:c#陣列問題

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more