簡體   English   中英

ManagedThreadId如何對應C#中的Thread和CPU上的Thread?

[英]How ManagedThreadId correspond to Thread in C# and Thread on CPU?

我試圖弄清楚C#如何管理線程。

我剛剛啟動了新的Web Api項目。 我把它打包到新Thread

public class Program                                                                       
{                                                                                          
    public static void Main(string[] args)                                                 
    {                                                                                      
        var thread = new Thread(() => CreateHostBuilder(args).Build().Run());              
        thread.Start();                                                                    
    }                                                                                      
                                                                                           
    public static IHostBuilder CreateHostBuilder(string[] args) =>                         
        Host.CreateDefaultBuilder(args)                                                    
            // DEFAULT STARTUP HERE
            .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); 
}          

我添加了我的自定義控制器:

[ApiController]                                      
[Route("[controller]")]                              
public class ValueController : ControllerBase        
{                                                    
    [HttpGet("fast")]                                
    public async Task<ActionResult<int[]>> Fast()    
    {                                                
        var task = new Task<int[]>(() =>             
        {                                            
            return new[] {1, 2, 3};                  
        });                                          
        task.Start();                                
                                                     
                                                     
        return Ok(await task);                       
    }                                                
                                                     
    [HttpGet("infinite")]                            
    public async Task<ActionResult<int[]>> Infinite()
    {                                                
        var task = new Task<int>(() =>               
        {                                            
            while (true)                             
            {                                        
            }                                        
                                                     
            return 0;                                
        });                                          
        task.Start();                                
                                                     
        return Ok(await task);                       
                                                     
    }                                                
}                                                    

首先,我運行https://localhost:5001/value/infinite端點來完成一項永遠不會在后台結束的任務。

然后我開始使用https://localhost:5001/value/infinite端點向我的應用發送垃圾郵件。

正如您在調試器中看到的:

端點的第一次運行:

在此處輸入圖片說明

第二:

在此處輸入圖片說明

整個ASP .NET應用程序在編號為@13272的同一線程上工作。

我的問題是,當后台有無限任務運行時可以運行多個任務時, .NET如何在一個線程中管理Tasks

在單個 OS 線程上運行多個用戶模式線程的概念稱為綠色線程或可能的纖程 .Net 不使用綠色線程。 雖然可以使用光纖,但它很少使用,通常被認為是過時的,在這種情況下不相關。

在 .Net 中,每個正在運行的任務都由一個托管線程運行,該線程由一個操作系統線程支持。 但是,調用task.Start()並不意味着任務正在運行,它只是將任務標記為掛起,即在有可用資源時可以運行。

完全有可能在任務開始之前查詢完成,並且相同的線程被重用於任務。

在您的示例中,還需要考慮網絡服務器組件。 我對 asp.Net 不是很熟悉,但我希望掛起的查詢最終會被運行時終止。

這是運行程序時發生的情況。

  1. 操作系統加載 .exe 映像並定位其main入口點。 這是您作為 ac# 程序員永遠不會看到的非托管端點。

  2. main入口點執行 .NET 引導程序; iload .NET 運行時、驗證您的 .exe、加載依賴程序集、建立堆和垃圾收集線程以及線程池。 然后它調用 c# 應用程序中的Main入口點。

  3. Main方法創建另一個線程,啟動它,並將控制權返回給引導程序。 在這一點上,你的程序或多或少地完成了。

  4. 您啟動的線程不是后台線程,因此它使您的應用程序保持打開狀態

  5. 您的線程調用IHostRun擴展方法。 根據文檔

運行應用程序並阻止調用線程直到主機關閉。

由於線程被阻塞,它將繼續存在,直到主機關閉。 這就是您獲得@13272線程的地方。

我不太了解這里的內部結構,但我懷疑這就是您的IHost最終要做的事情:

  1. 向操作系統注冊 TCP/IP 偵聽器,例如建立回調。
  2. 當流量到達時,O/S 調用回調。
  3. 回調由主機處理,它實例化您的控制器並異步調用操作方法。
  4. 在動作方法“返回”后(動作方法要么完成,要么使用await來讓出控制),它會檢查任務是否完成。 如果不是,則將其延續的任務放在線程池中,以便在適當的時候執行。

主機所做的所有事情都可能發生在任何線程上,這就是這些 ID 不斷變化的原因。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM