簡體   English   中英

當您阻塞同步方法的異步包裝器時,資源會發生什么情況?

[英]What happens to the resources when you block on a asynchronous wrapper for a synchronous method?

我在我們的生產代碼庫中看到了一些遵循如下模式的奇怪代碼。 我想知道調用Start()與直接運行同步代碼相比對性能有何影響。 特別是在這種情況下如何管理任務或線程。

public Task RunLongTask(){
    return Task.Run(()=>{
       // Run some Synchronous long IO process
    }
}

public void Start(){
    RunLongTask().Wait();
}

我的想法是否正確,在等待同步 IO 調用完成時,一項任務將被阻塞。 並且RunLongTask()上的調用者也將被阻止。 本質上使直接運行同步代碼的成本加倍。 由於雙阻塞,在這種情況下是否總是會創建 2 個線程?

根據MSDNTask.Run方法將指定的工作排隊以在ThreadPool上運行。 Task.Wait方法正在阻塞一個。 可以在這篇文章中找到對此的簡單解釋

即使底層任務是異步的,如果您在任務上調用阻塞方法或阻塞屬性,執行也會等待任務完成——但會同步執行,這樣當前線程在等待期間完全被占用。 因此,如果您使用上述屬性/方法之一,請確保這確實是您想要做的。

因此,您當前的線程(執行RunLongTask().Wait(); )將被阻塞,直到此Task中的工作同步完成

Task.Run(()=>{
       // Run some Synchronous long IO process
    }

直接運行同步代碼不會加倍,您的主線程只是被阻塞並等待 I/O 過程在單獨的線程上完成

由於雙阻塞,在這種情況下是否總是會創建 2 個線程?

您已經至少有一個Thread ,當前的一個正在調用Task.Run Task.Run將從線程池(如果有的話)中獲得一個空閑的工作線程,但它將是一個不同的線程。

就性能而言,在單獨的線程上運行 I/O 操作不是很有效(因為它可能用於 CPU 綁定工作),因為工作線程將主要等待發送/接收數據。 最好使您的長 IO 進程異步並在不阻塞的情況下運行它(當然,如果它支持異步 API)。

另一個潛在的性能缺陷是 ASP.NET Core 每個請求使用一個線程,並且運行具有長時間運行 IO 進程的后台線程將減少可用於處理新請求的線程數(以及應用程序的可伸縮性)

暫無
暫無

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

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