国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

async/await 在 C# 語言中是如何工作的?(下)

這篇具有很好參考價值的文章主要介紹了async/await 在 C# 語言中是如何工作的?(下)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

接《async/await 在 C# 語言中是如何工作的?(上)》、《async/await 在 C# 語言中是如何工作的?(中)》,今天我們繼續(xù)介紹?SynchronizationContext 和 ConfigureAwait。

?

▌SynchronizationContext 和 ConfigureAwait

我們之前在 EAP 模式的上下文中討論過 SynchronizationContext,并提到它將再次出現(xiàn)。SynchronizationContext 使得調(diào)用可重用的輔助函數(shù)成為可能,并自動被調(diào)度回調(diào)用環(huán)境認(rèn)為合適的任何地方。因此,我們很自然地認(rèn)為 async/await 能“正常工作”,事實也的確如此?;氐角懊娴陌粹o單擊處理程序:

ThreadPool.QueueUserWorkItem(_ =>{    string message = ComputeMessage();    button1.BeginInvoke(() =>    {        button1.Text = message;    });});

使用 async/await,我們可以這樣寫:

button1.Text = await Task.Run(() => ComputeMessage());

對 ComputeMessage 的調(diào)用被轉(zhuǎn)移到線程池中,這個方法執(zhí)行完畢后,執(zhí)行又轉(zhuǎn)移回與按鈕關(guān)聯(lián)的 UI 線程,設(shè)置按鈕的 Text 屬性就是在這個線程中進(jìn)行的。

與 SynchronizationContext 的集成由 awaiter 實現(xiàn)(為狀態(tài)機(jī)生成的代碼對 SynchronizationContext 一無所知),因為當(dāng)所表示的異步操作完成時,是 awaiter 負(fù)責(zé)實際調(diào)用或?qū)⑺峁┑?continuation 排隊。而自定義 awaiter 不需要考慮 SynchronizationContext。目前,Task、Task<TResult>、ValueTask、ValueTask<TResult> 的等待器都是 do。這意味著,默認(rèn)情況下,當(dāng)你等待一個任務(wù),一個 Task<TResult>,一個 ValueTask,一個 ValueTask<TResult>,甚至 Task. yield() 調(diào)用的結(jié)果時,awaiter 默認(rèn)會查找當(dāng)前的 SynchronizationContext,如果它成功地獲得了一個非默認(rèn)的同步上下文,最終會將 continuation 排隊到該上下文。

如果我們查看 TaskAwaiter 中涉及的代碼,就可以看到這一點(diǎn)。以下是 Corelib 中的相關(guān)代碼片段:???????

internal void UnsafeSetContinuationForAwait(IAsyncStateMachineBox stateMachineBox, bool continueOnCapturedContext){    if (continueOnCapturedContext)    {        SynchronizationContext? syncCtx = SynchronizationContext.Current;        if (syncCtx != null && syncCtx.GetType() != typeof(SynchronizationContext))        {            var tc = new SynchronizationContextAwaitTaskContinuation(syncCtx, stateMachineBox.MoveNextAction, flowExecutionContext: false);            if (!AddTaskContinuation(tc, addBeforeOthers: false))            {                tc.Run(this, canInlineContinuationTask: false);            }            return;        }        else        {            TaskScheduler? scheduler = TaskScheduler.InternalCurrent;            if (scheduler != null && scheduler != TaskScheduler.Default)            {                var tc = new TaskSchedulerAwaitTaskContinuation(scheduler, stateMachineBox.MoveNextAction, flowExecutionContext: false);                if (!AddTaskContinuation(tc, addBeforeOthers: false))                {                    tc.Run(this, canInlineContinuationTask: false);                }                return;            }        }    }
    ...}

這是一個方法的一部分,用于確定將哪個對象作為 continuation 存儲到任務(wù)中。它被傳遞給 stateMachineBox,如前所述,它可以直接存儲到任務(wù)的 continuation 列表中。但是,這個特殊的邏輯可能會將 IAsyncStateMachineBox 封裝起來,以合并一個調(diào)度程序(如果存在的話)。它檢查當(dāng)前是否有非默認(rèn)的 SynchronizationContext,如果有,它會創(chuàng)建一個 SynchronizationContextAwaitTaskContinuation 作為實際的對象,它會被存儲為 continuation;該對象依次包裝了原始的和捕獲的 SynchronizationContext,并知道如何在與后者排隊的工作項中調(diào)用前者的 MoveNext。這就是如何在 UI 應(yīng)用程序中作為事件處理程序的一部分等待,并在等待完成后讓代碼繼續(xù)在正確的線程上運(yùn)行。這里要注意的下一個有趣的事情是,它不僅僅關(guān)注一個 SynchronizationContext:如果它找不到一個自定義的 SynchronizationContext 來使用,它還會查看 Tasks 使用的 TaskScheduler 類型是否有一個需要考慮的自定義類型。和 SynchronizationContext 一樣,如果有一個非默認(rèn)值,它就會和原始框一起包裝在 TaskSchedulerAwaitTaskContinuation 中,用作 continuation 對象。

但這里最值得注意的可能是方法主體的第一行:if (continueOnCapturedContext)。我們只在 continueOnCapturedContext 為 true 時才對 SynchronizationContext/TaskScheduler 進(jìn)行這些檢查;如果這個值為 false,實現(xiàn)方式就好像兩者都是默認(rèn)值一樣,會忽略它們。請問是什么將 continueOnCapturedContext 設(shè)置為 false?你可能已經(jīng)猜到了:使用非常流行的 ConfigureAwait(false)。

可以這樣說,作為 await 的一部分,ConfigureAwait(false) 做的唯一一件事是將它的參數(shù)布爾值作為 continueOnCapturedContext 值提供給這個函數(shù)(以及其他類似的函數(shù)),以便跳過對 SynchronizationContext/TaskScheduler 的檢查,表現(xiàn)得好像它們都不存在一樣。對于進(jìn)程來說,這允許 Task 在它認(rèn)為合適的地方調(diào)用其 continuation,而不是強(qiáng)制將它們排隊在某個特定的調(diào)度器上執(zhí)行。

我之前提到過 SynchronizationContext 的另一個方面,我說過我們會再次看到它:OperationStarted/OperationCompleted?,F(xiàn)在是時候了。這是沒那么受歡迎的特性:異步 void。除了 configureawait 之外,async void 可以說是 async/await 中最具爭議性的特性之一。它被添加的原因只有一個:事件處理程序。在 UI 應(yīng)用程序中,你可以編寫如下代碼:???????

button1.Click += async (sender, eventArgs) =>{  button1.Text = await Task.Run(() => ComputeMessage());  };

但如果所有的異步方法都必須有一個像 Task 這樣的返回類型,你就不能這樣做了。Click 事件有一個簽名 public event EventHandler? Click;,其中 EventHandler 定義為 public delegate void EventHandler(object? sender, EventArgs e);,因此要提供一個符合該簽名的方法,該方法需要是 void-returning。

有各種各樣的理由認(rèn)為 async void 是不好的,為什么文章建議盡可能避免使用它,以及為什么出現(xiàn)了各種?analyzers?來標(biāo)記使用 async void。最大的問題之一是委托推理??紤]下面的程序:???????

using System.Diagnostics;
Time(async () =>{    Console.WriteLine("Enter");    await Task.Delay(TimeSpan.FromSeconds(10));    Console.WriteLine("Exit");});
static void Time(Action action){    Console.WriteLine("Timing...");    Stopwatch sw = Stopwatch.StartNew();    action();    Console.WriteLine($"...done timing: {sw.Elapsed}");}

人們很容易期望它輸出至少10秒的運(yùn)行時間,但如果你運(yùn)行它,你會發(fā)現(xiàn)輸出是這樣的:???????

Timing...Enter...done timing: 00:00:00.0037550

async lambda 實際上是一個異步 void 方法。異步方法會在遇到第一個暫停點(diǎn)時返回調(diào)用者。如果這是一個異步 Task 方法,Task 就會在這個時間點(diǎn)返回。但對于 async void,什么都不會返回。Time 方法只知道它調(diào)用了 action();委托調(diào)用返回;它不知道 async 方法實際上仍在“運(yùn)行”,并將在稍后異步完成。

這就是 OperationStarted/OperationCompleted 的作用。這種異步 void 方法本質(zhì)上與前面討論的 EAP 方法類似:這種方法的初始化是 void,因此需要一些其他機(jī)制來跟蹤所有此類操作。因此,EAP 實現(xiàn)在操作啟動時調(diào)用當(dāng)前 SynchronizationContext 的 OperationStarted,在操作完成時調(diào)用 OperationCompleted,async void 也做同樣的事情。與 async void 相關(guān)的構(gòu)建器是 AsyncVoidMethodBuilder。還記得在 async 方法的入口,編譯器生成的代碼如何調(diào)用構(gòu)建器的靜態(tài) Create 方法來獲得適當(dāng)?shù)臉?gòu)建器實例嗎?AsyncVoidMethodBuilder 利用了這一點(diǎn)來掛鉤創(chuàng)建和調(diào)用 OperationStarted:???????

public static AsyncVoidMethodBuilder Create(){    SynchronizationContext? sc = SynchronizationContext.Current;    sc?.OperationStarted();    return new AsyncVoidMethodBuilder() { _synchronizationContext = sc };}

類似地,當(dāng)通過 SetResult 或 SetException 將構(gòu)建器標(biāo)記為完成時,它會調(diào)用相應(yīng)的 OperationCompleted 方法。這就是像 xunit 這樣的單元測試框架如何能夠具有異步 void 測試方法,并仍然在并發(fā)測試執(zhí)行中使用最大程度的并發(fā),例如在 xunit 的?AsyncTestSyncContext?中。

有了這些知識,現(xiàn)在可以重寫我們的 timing 示例:???????

using System.Diagnostics;
Time(async () =>{    Console.WriteLine("Enter");    await Task.Delay(TimeSpan.FromSeconds(10));    Console.WriteLine("Exit");});
static void Time(Action action){    var oldCtx = SynchronizationContext.Current;    try    {        var newCtx = new CountdownContext();        SynchronizationContext.SetSynchronizationContext(newCtx);
        Console.WriteLine("Timing...");        Stopwatch sw = Stopwatch.StartNew();                action();        newCtx.SignalAndWait();
        Console.WriteLine($"...done timing: {sw.Elapsed}");    }    finally    {        SynchronizationContext.SetSynchronizationContext(oldCtx);    }}
sealed class CountdownContext : SynchronizationContext{    private readonly ManualResetEventSlim _mres = new ManualResetEventSlim(false);    private int _remaining = 1;
    public override void OperationStarted() => Interlocked.Increment(ref _remaining);
    public override void OperationCompleted()    {        if (Interlocked.Decrement(ref _remaining) == 0)        {            _mres.Set();        }    }
    public void SignalAndWait()    {        OperationCompleted();        _mres.Wait();    }}

在這里,我已經(jīng)創(chuàng)建了一個 SynchronizationContext,它跟蹤了一個待定操作的計數(shù),并支持阻塞等待它們?nèi)客瓿?。?dāng)我運(yùn)行它時,我得到這樣的輸出:???????

Timing...EnterExit...done timing: 00:00:10.0149074

?

▌State Machine Fields

至此,我們已經(jīng)看到了生成的入口點(diǎn)方法,以及 MoveNext 實現(xiàn)中的一切是如何工作的。我們還了解了在狀態(tài)機(jī)上定義的一些字段。讓我們仔細(xì)看看這些。

對于前面給出的 CopyStreamToStream 方法:???????

public async Task CopyStreamToStreamAsync(Stream source, Stream destination){    var buffer = new byte[0x1000];    int numRead;    while ((numRead = await source.ReadAsync(buffer, 0, buffer.Length)) != 0)    {        await destination.WriteAsync(buffer, 0, numRead);    }}

下面是我們最終得到的字段:???????

private struct <CopyStreamToStreamAsync>d__0 : IAsyncStateMachine{    public int <>1__state;    public AsyncTaskMethodBuilder <>t__builder;    public Stream source;    public Stream destination;    private byte[] <buffer>5__2;    private TaskAwaiter <>u__1;    private TaskAwaiter<int> <>u__2;
    ...}

< > 1 __state。是“狀態(tài)機(jī)”中的“狀態(tài)”。它定義了狀態(tài)機(jī)所處的當(dāng)前狀態(tài),最重要的是下次調(diào)用 MoveNext 時應(yīng)該做什么。如果狀態(tài)為-2,則操作完成。如果狀態(tài)是-1,要么是我們第一次調(diào)用 MoveNext,要么是 MoveNext 代碼正在某個線程上運(yùn)行。如果你正在調(diào)試一個 async 方法的處理過程,并且你看到狀態(tài)為-1,這意味著在某處有某個線程正在執(zhí)行包含在方法中的代碼。如果狀態(tài)大于等于0,方法會被掛起,狀態(tài)的值會告訴你在什么時候掛起。雖然這不是一個嚴(yán)格的規(guī)則(某些代碼模式可能會混淆編號),但通常情況下,分配的狀態(tài)對應(yīng)于從0開始的 await 編號,按照源代碼從上到下的順序排列。例如,如果 async 方法的函數(shù)體完全是:???????

await A();await B();await C();await D();

你發(fā)現(xiàn)狀態(tài)值是2,這幾乎肯定意味著 async 方法當(dāng)前被掛起,等待從 C() 返回的任務(wù)完成。

< > t__builder。這是狀態(tài)機(jī)的構(gòu)建器,例如用于 Task 的 AsyncTaskMethodBuilder,用于 ValueTask 的 AsyncValueTaskMethodBuilder<TResult>,用于 async void 方法的 AsyncVoidMethodBuilder,或用于 async 返回類型的 AsyncMethodBuilder(…)] 或通過 async 方法本身的屬性覆蓋的任何構(gòu)建器。如前所述,構(gòu)建器負(fù)責(zé) async 方法的生命周期,包括創(chuàng)建 return 任務(wù),最終完成該任務(wù),并充當(dāng)暫停的中介,async 方法中的代碼要求構(gòu)建器暫停,直到特定的 awaiter 完成。

編譯器完全按照參數(shù)名稱的指定來命名它們。如前所述,所有被方法主體使用的參數(shù)都需要被存儲到狀態(tài)機(jī)中,以便 MoveNext 方法能夠訪問它們。注意我說的是 "被使用"。如果編譯器發(fā)現(xiàn)一個參數(shù)沒有被異步方法的主體使用,它就可以優(yōu)化,不需要存儲這個字段。例如,給定下面的方法:???????

public async Task M(int someArgument){    await Task.Yield();}

編譯器會將這些字段發(fā)送到狀態(tài)機(jī):???????

private struct <M>d__0 : IAsyncStateMachine{    public int <>1__state;    public AsyncTaskMethodBuilder <>t__builder;    private YieldAwaitable.YieldAwaiter <>u__1;    ...}

請注意,這里明顯缺少名為 someArgument 的參數(shù)。但是,如果我們改變 async 方法,讓它以任何方式使用實參:???????

public async Task M(int someArgument){    Console.WriteLine(someArgument);    await Task.Yield();}

它顯示:???????

private struct <M>d__0 : IAsyncStateMachine{    public int <>1__state;    public AsyncTaskMethodBuilder <>t__builder;    public int someArgument;    private YieldAwaitable.YieldAwaiter <>u__1;    ...}

<buffer>5__2;。這是緩沖區(qū)的 "局部",它被提升為一個字段,這樣它就可以在等待點(diǎn)上存活。編譯器相當(dāng)努力地防止?fàn)顟B(tài)被不必要地提升。注意,在源碼中還有一個局部變量 numRead,在狀態(tài)機(jī)中沒有相應(yīng)的字段。為什么?因為它沒有必要。這個局部變量被設(shè)置為 ReadAsync 調(diào)用的結(jié)果,然后被用作 WriteAsync 調(diào)用的輸入。在這兩者之間沒有 await,因此 numRead 的值需要被存儲。就像在一個同步方法中,JIT 編譯器可以選擇將這樣的值完全存儲在一個寄存器中,而不會真正將其溢出到堆棧中,C# 編譯器可以避免將這個局部變量提升為一個字段,因為它不需要在任何等待中保存它的值。一般來說,如果 C# 編譯器能夠證明局部變量的值不需要在等待中保存,它就可以省略局部變量的提升。

<>u__1和<>u__2。async 方法中有兩個 await:一個用于 ReadAsync 返回的 Task<int>,另一個用于 WriteAsync 返回的 Task。Task. getawaiter() 返回一個 TaskAwaiter,Task<TResult>. getawaiter() 返回一個 TaskAwaiter<TResult>,兩者都是不同的結(jié)構(gòu)體類型。由于編譯器需要在 await (IsCompleted, UnsafeOnCompleted) 之前獲取這些 awaiter,然后需要在 await (GetResult) 之后訪問它們,因此需要存儲這些 awaiter。由于它們是不同的結(jié)構(gòu)類型,編譯器需要維護(hù)兩個單獨(dú)的字段來做到這一點(diǎn)(另一種選擇是將它們裝箱,并為 awaiter 提供一個對象字段,但這會導(dǎo)致額外的分配成本)。不過,編譯器會盡可能地重復(fù)使用字段。如果我有:???????

public async Task M(){    await Task.FromResult(1);    await Task.FromResult(true);    await Task.FromResult(2);    await Task.FromResult(false);    await Task.FromResult(3);}

有五個等待,但只涉及兩種不同類型的等待者:三個是 TaskAwaiter<int>,兩個是 TaskAwaiter<bool>。因此,狀態(tài)機(jī)上最終只有兩個等待者字段:

private struct <M>d__0 : IAsyncStateMachine{    public int <>1__state;    public AsyncTaskMethodBuilder <>t__builder;    private TaskAwaiter<int> <>u__1;    private TaskAwaiter<bool> <>u__2;    ...}

然后,如果我將我的示例改為:???????

public async Task M(){    await Task.FromResult(1);    await Task.FromResult(true);    await Task.FromResult(2).ConfigureAwait(false);    await Task.FromResult(false).ConfigureAwait(false);    await Task.FromResult(3);}

仍然只涉及 Task<int>s 和 Task<bool>s,但實際上我使用了四個不同的 struct awaiter 類型,因為從 ConfigureAwait 返回的東西上的 GetAwaiter() 調(diào)用返回的 awaiter 與 Task.GetAwaiter() 返回的是不同的類型…從編譯器創(chuàng)建的 awaiter 字段可以再次很明顯的看出:???????

private struct <M>d__0 : IAsyncStateMachine{    public int <>1__state;    public AsyncTaskMethodBuilder <>t__builder;    private TaskAwaiter<int> <>u__1;    private TaskAwaiter<bool> <>u__2;    private ConfiguredTaskAwaitable<int>.ConfiguredTaskAwaiter <>u__3;    private ConfiguredTaskAwaitable<bool>.ConfiguredTaskAwaiter <>u__4;    ...}

如果您發(fā)現(xiàn)自己想要優(yōu)化與異步狀態(tài)機(jī)相關(guān)的大小,您可以查看的一件事是是否可以合并正在等待的事情,從而合并這些 awaiter 字段。

您可能還會看到在狀態(tài)機(jī)上定義的其他類型的字段。值得注意的是,您可能會看到一些字段包含單詞“wrap”??紤]下面這個例子:

public async Task<int> M() => await Task.FromResult(42) + DateTime.Now.Second;

這將生成一個包含以下字段的狀態(tài)機(jī):???????

private struct <M>d__0 : IAsyncStateMachine{    public int <>1__state;    public AsyncTaskMethodBuilder<int> <>t__builder;    private TaskAwaiter<int> <>u__1;    ...}

到目前為止沒有什么特別的?,F(xiàn)在顛倒一下添加表達(dá)式的順序:

public async Task<int> M() => DateTime.Now.Second + await Task.FromResult(42);

這樣,你就得到了這些字段:???????

private struct <M>d__0 : IAsyncStateMachine{    public int <>1__state;    public AsyncTaskMethodBuilder<int> <>t__builder;    private int <>7__wrap1;    private TaskAwaiter<int> <>u__1;    ...}

我們現(xiàn)在有了另一個函數(shù):<>7__wrap1。為什么?因為我們計算了 DateTime.Now 的值。其次,只有在計算完它之后,我們才需要等待一些東西,并且需要保留第一個表達(dá)式的值,以便將其與第二個表達(dá)式的結(jié)果相加。因此,編譯器需要確保第一個表達(dá)式的臨時結(jié)果可以添加到 await 的結(jié)果中,這意味著它需要將表達(dá)式的結(jié)果溢出到臨時中,它使用 <>7__wrap1 字段做到了這一點(diǎn)。如果你發(fā)現(xiàn)自己對異步方法的實現(xiàn)進(jìn)行了超優(yōu)化,以減少分配的內(nèi)存量,你可以尋找這樣的字段,并查看對源代碼的微調(diào)是否可以避免溢出的需要,從而避免這種臨時的需要。

async/await 在 C# 語言中是如何工作的?(下)

我希望這篇文章有助于解釋當(dāng)你使用 async/await 時背后到底發(fā)生了什么。這里有很多變化,所有這些結(jié)合在一起,創(chuàng)建了一個高效的解決方案,可以編寫可拓展的異步代碼,而不必處理回調(diào)。然而歸根結(jié)底,這些部分實際上是相對簡單的:任何異步操作的通用表示,一種能夠?qū)⑵胀刂屏髦貙憺閰f(xié)程的狀態(tài)機(jī)實現(xiàn)的語言和編譯器,以及將它們綁定在一起的模式。其他一切都是優(yōu)化的額外收獲。

編程愉快!

點(diǎn)我前往原博客~文章來源地址http://www.zghlxwxcb.cn/news/detail-477159.html

到了這里,關(guān)于async/await 在 C# 語言中是如何工作的?(下)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • C#中await /async 的使用場景,優(yōu)點(diǎn),使用方法介紹

    C#中await /async 的使用場景,優(yōu)點(diǎn),使用方法介紹

    ? async/await ?是 C# 中異步編程的關(guān)鍵特性,它使得異步代碼編寫更為簡單和直觀。下面深入詳細(xì)描述了? async/await ?的使用場景、優(yōu)點(diǎn)以及一些高級使用方法,并提供了相應(yīng)的實例源代碼。 I/O 操作: ?異步編程特別適用于涉及 I/O 操作(如文件讀寫、網(wǎng)絡(luò)請求等)的場景。在

    2024年02月05日
    瀏覽(17)
  • Unity C# 之 Task、async和 await 結(jié)合使用的一些情況處理

    目錄 Unity C# 之 Task、async和 await? 結(jié)合使用的一些情況處理 一、簡單介紹 二、把 async 函數(shù),通過變化轉(zhuǎn)為一般的函數(shù) 三、在 async 函數(shù)中,切換到主線程,并等待主線程執(zhí)行完畢,繼續(xù) async 中的代碼 Unity 在使用 Task 結(jié)合 async (await) 的時候,偶爾會遇到一些特殊情況,需要

    2024年01月22日
    瀏覽(21)
  • 深入探討 C# 和 .NET 中 async/await 的歷史、背后的設(shè)計決策和實現(xiàn)細(xì)節(jié)

    對 async/await 的支持已經(jīng)存在了十多年。它的出現(xiàn),改變了為 .NET 編寫可伸縮代碼的方式,你在不了解幕后的情況下也可以非常普遍地使用該功能。 從如下所示的同步方法開始(此方法是“ 同步的 ”,因為在整個操作完成并將控制權(quán)返回給調(diào)用方之前,調(diào)用方將無法執(zhí)行任何

    2024年02月08日
    瀏覽(28)
  • Unity C# 之 Task、async和 await 、Thread 基礎(chǔ)使用的Task的簡單整理

    Unity C# 之 Task、async和 await 、Thread 基礎(chǔ)使用的Task的簡單整理

    目錄 Unity C# 之 Task、async和 await 、Thread 基礎(chǔ)使用的Task的簡單整理 一、Task、async和 await 、Thread 基礎(chǔ)概念 1、線程,多線程 2、Task ?3、async (await ) 二、Task 的基礎(chǔ)使用,Task 的創(chuàng)建 和 啟動 1、創(chuàng)建并運(yùn)行一個Task 2、創(chuàng)建有返回值的 Task 3、Task提供了 task.RunSynchronously()用于同步

    2024年02月12日
    瀏覽(19)
  • Unity中的異步編程【5】——在Unity中使用 C#原生的異步(Task,await,async) - System.Threading.Tasks

    Unity中的異步編程【5】——在Unity中使用 C#原生的異步(Task,await,async) - System.Threading.Tasks

    1、System.Threading.Tasks中的Task是.Net原生的異步和多線程包。 2、UniTask(Cysharp.Threading.Tasks)是仿照.Net原生的Task,await,async開發(fā)的一個包,該包專門服務(wù)于Unity,所以取名UnityTask,簡稱UniTask。 3、既然有Task了,為啥還要搞一個UniTask (1)Task可以用在PC和Android上,但是在WebGL上則會

    2023年04月17日
    瀏覽(25)
  • 我在工作中是如何使用【Linux】的

    目錄 前言 一.常用命令 二.文件和目錄處理 三.用戶與組管理命令 四.進(jìn)程管理命令 五.網(wǎng)絡(luò)管理命令 六-.幫助命令 七.磁盤管理 大家好,這是我首篇博客,內(nèi)容是linux工作需用到的內(nèi)容。在這里我給大家總結(jié)出來了,希望多支持支持,感謝 date? 顯示日期 1.date --help命令顯示

    2024年02月06日
    瀏覽(15)
  • Swift async/await 并發(fā)中如何將任務(wù)組(TaskGroup)轉(zhuǎn)換為異步序列(AsyncSequence)

    Swift async/await 并發(fā)中如何將任務(wù)組(TaskGroup)轉(zhuǎn)換為異步序列(AsyncSequence)

    在 Swift 新結(jié)構(gòu)化并行模型的開發(fā)中,? 提出了任務(wù)組(TaskGroup)和異步序列(AsyncSequence)的概念。有時候,為了簡潔和效率方面的原因,我們需要將 TaskGroup 的結(jié)果轉(zhuǎn)換為異步序列。 如上圖所示,我們試圖將任務(wù)組的結(jié)果轉(zhuǎn)換為異步序列,但不幸失敗了。 那么,最終我們到

    2024年02月12日
    瀏覽(23)
  • Unity C# 之 使用 HttpWebRequest 基礎(chǔ)知識/HttpWebRequest 進(jìn)行異步Post 網(wǎng)絡(luò)訪問/數(shù)據(jù)流形式獲取數(shù)據(jù)(Task/async/await)的代碼簡單實現(xiàn)

    Unity C# 之 使用 HttpWebRequest 基礎(chǔ)知識/HttpWebRequest 進(jìn)行異步Post 網(wǎng)絡(luò)訪問/數(shù)據(jù)流形式獲取數(shù)據(jù)(Task/async/await)的代碼簡單實現(xiàn)

    目錄 Unity C# 之 使用 HttpWebRequest 基礎(chǔ)知識/HttpWebRequest 進(jìn)行異步Post 網(wǎng)絡(luò)訪問/數(shù)據(jù)流形式獲取數(shù)據(jù)(Task/async/await)的代碼簡單實現(xiàn) 一、簡單介紹 二、實現(xiàn)原理 三、注意事項 四、效果預(yù)覽 五、關(guān)鍵代碼 附錄 : HttpWebRequest 的一些基礎(chǔ)知識 1、HttpWebRequest 常用屬性 2、HttpWebRequest?

    2024年02月05日
    瀏覽(25)
  • 什么是Promise對象?它的狀態(tài)有哪些?如何使用Promise處理異步操作?以及 async、await

    什么是Promise對象?它的狀態(tài)有哪些?如何使用Promise處理異步操作?以及 async、await

    前端入門之旅:探索Web開發(fā)的奇妙世界 記得點(diǎn)擊上方或者右側(cè)鏈接訂閱本專欄哦 幾何帶你啟航前端之旅 歡迎來到前端入門之旅!這個專欄是為那些對Web開發(fā)感興趣、剛剛踏入前端領(lǐng)域的朋友們量身打造的。無論你是完全的新手還是有一些基礎(chǔ)的開發(fā)者,這里都將為你提供一

    2024年02月11日
    瀏覽(52)
  • async和await

    Node.JS官方文檔:https://nodejs.dev/en/ 創(chuàng)建異步函數(shù),并返回相關(guān)數(shù)值: 一般方式創(chuàng)建 通過async方式創(chuàng)建: 在async聲明的函數(shù)中可以使用await來調(diào)用異步函數(shù) 當(dāng)我們通過await去調(diào)用異步函數(shù)時候,它會暫停代碼的運(yùn)行 直到異步代碼執(zhí)行有結(jié)果時,才會將結(jié)果返回 注意 awa

    2024年02月02日
    瀏覽(21)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包