假設我有以下簡單程式,它在 DownloadDocsMainPageAsync() 和 Main() 中都使用了 await 運算子。雖然我知道當前的可等待方法會在結果可用后暫停并從該點繼續,但我需要澄清以下幾點。
a) 如果 Main() 的執行從執行緒池的執行緒 A 開始,一旦遇到 await 運算子,該執行緒就會回傳到執行緒池以執行程式中的其他操作,例如:如果它是一個 web 應用程式,那么從 UI 中單擊按鈕后呼叫某些控制器方法?
b) await 運算子是否總是在執行緒池中的新執行緒上執行,或者在這種情況下假設除了 Main() 沒有其他方法可以執行,它會繼續在同一個執行緒本身(ThreadA)上執行嗎?如果我的理解是正確的,是誰決定的,是 CLR 的垃圾收集器嗎?
using System;
using System.Net.Http;
using System.Threading.Tasks;
public class AwaitOperator
{
public static async Task Main()
{
Task<int> downloading = DownloadDocsMainPageAsync();
Console.WriteLine($"{nameof(Main)}: Launched downloading.");
int bytesLoaded = await downloading;
Console.WriteLine($"{nameof(Main)}: Downloaded {bytesLoaded} bytes.");
}
private static async Task<int> DownloadDocsMainPageAsync()
{
Console.WriteLine($"{nameof(DownloadDocsMainPageAsync)}: About to start downloading.");
var client = new HttpClient();
byte[] content = await client.GetByteArrayAsync("https://docs.microsoft.com/en-us/");
Console.WriteLine($"{nameof(DownloadDocsMainPageAsync)}: Finished downloading.");
return content.Length;
}
}
uj5u.com熱心網友回復:
實際上,async/await不是關于執行緒(幾乎),而只是關于控制流控制。因此,在您的代碼執行中,進入 Main 執行緒(順便說一下,它不是來自執行緒池),直到達到await client.GetByteArrayAsync. 這里真正的低級下載在內部被卸載到作業系統級別,程式只是等待下載結果。仍然沒有產生額外的執行緒。但是,下載完成后,.NET 運行時希望在await. 在這里它可以看到沒有SynchronizationContext(因為控制臺應用程式沒有它),然后運行時await在執行緒池中可用的任何執行緒中執行代碼。因此,下載后的其余代碼將在池中的線??程中執行。
如果您要添加一個SynchronizationContext(或只是在 WinForms 應用程式中移動背景關系存在開箱即用的代碼),您將看到所有代碼都將在主執行緒中執行,不會從作為運行時的執行緒池將看到 SynchronizationContext 并將在原始執行緒上調度 after-await 代碼。
所以,答案
a)Main在主執行緒上開始,而不是在執行緒池的執行緒上。await它本身實際上并不產生任何執行緒。在 上await,如果當前執行緒來自執行緒池,則該執行緒將放回執行緒池中,并可用于以后的作業。有一個例外,當await將立即同步繼續時(見下文)。
SynchronizationContextb) 運行時根據當前、ConfigureAwait設定和到達等待時刻操作結果的可用性決定在“等待”之后將繼續執行哪個執行緒。
特別是
如果
SynchronizationContext存在并ConfigureAwait設定為true(或省略),則代碼始終在當前執行緒中繼續。如果
SynchronizationContext不存在或ConfigureAwait設定為false,代碼將在任何可用執行緒(主執行緒或執行緒池)中繼續如果你寫類似
var task = DoSomeWorkAsync(); //some synchronous work which takes a while await task;那么你可以有一種情況,當
task代碼到達的那一刻已經完成await。在這種情況下,運行時可以在同一執行緒中await同步后繼續執行。但據我所知,這種情況是特定于實作的。此外,這是一個特殊的類(此處
TaskCompletionSource<TResult>的檔案),它提供對任務狀態的顯式控制,特別是可以在代碼擁有實體選擇的任何執行緒上切換執行(參見@TheodorZoulias 評論中的示例或此處)。TaskCompletionSource
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/417324.html
標籤:
下一篇:UI和作業執行緒之間的執行緒同步
