第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

為什么在不將其分配給 Task 變量的情況下直接等待異步函數(shù)不起作用

為什么在不將其分配給 Task 變量的情況下直接等待異步函數(shù)不起作用

C#
素胚勾勒不出你 2021-11-21 14:32:18
通常,我會執(zhí)行以下操作public static async Task dosth(){    List<Task> job = new List<Task>();    for (int i = 0; i < 3; i++)    {        job.Add(sleep());    }    Task.WhenAll(job.ToArray());}static async Task sleep(){    await Task.Delay(1000);    Console.WriteLine("Finish new");}它工作順利,沒有問題。但是當(dāng)我對自己的代碼進行審查時(嘗試使用其他語法來完成相同的工作),我突然發(fā)現(xiàn)以下兩個是不同的。public static async Task dosthA(){    //This will be working synchronously, take 3 seconds.    await sleep();    await sleep();    await sleep();    //This will be working asynchronously, take 1 second only.    Task A = sleep();    Task B = sleep();    Task C = sleep();    await A;    await B;    await C;}為什么將異步函數(shù)分配給新變量會有所不同?我原本認為它們是一樣的。更新為什么讓我感到困惑的是,實際上在Async-await 的 Microsoft 文檔中,他們在代碼中聲明了以下內(nèi)容。// Calls to TaskOfTResult_MethodAsync  Task<int> returnedTaskTResult = TaskOfTResult_MethodAsync();  int intResult = await returnedTaskTResult;  // or, in a single statement  int intResult = await TaskOfTResult_MethodAsync();  他們實際上是不同的,為什么他們使用//or , in a single statement,僅僅因為它在他們自己的例子中沒有什么不同?
查看完整描述

1 回答

?
函數(shù)式編程

TA貢獻1807條經(jīng)驗 獲得超9個贊

這是因為當(dāng)您Task在調(diào)用Sleep()時返回運行時,即使您正在分配變量。


令人困惑的是,Task如果您在調(diào)用之前將其分配給變量(、 或)A,則不會開始B,但事實并非如此。一旦你分配給,就被調(diào)用了;因此in方法正在運行。將其分配給變量與否在調(diào)用方法時開始;因為在你啟動的方法中。 Cawait A; sleep();Asleep()Tasksleep()TaskTask


知道這一點;你打電話時:


await A;

await B;

await C;

A、B 和 C 已經(jīng)同時開始……在等待 A 之后,很可能 B 和 C 也已完成或距離完成幾毫秒。


在某些情況下,您可以引用Task尚未啟動的a ,但您必須有意返回非運行Task才能執(zhí)行此操作。


還要回答對您的問題的編輯。


Tasks 有一個被調(diào)用的方法GetAwaiter(),它返回一個TaskAwaiter. 在 C# 中,當(dāng)您編寫時,您var task = sleep();將實際分配給Task任務(wù)變量。同樣,當(dāng)你編寫await sleep();編譯器時,它會做一些很酷的事情,并且它實際上會調(diào)用Task.GetAwaiter()方法;這是訂閱的。在Task將運行并完成時,TaskAwaiter將觸發(fā)延續(xù)動作。這不能用簡單的答案來解釋,但了解外部邏輯會有所幫助。


除其他外,TaskAwaiter工具ICriticalNotifyCompletion又會執(zhí)行INotifyCompletion。兩者都有一個方法,OnCompleted(Action)并且UnsafeOnCompleted(Action) (您可以通過命名約定猜測哪個是哪個)。


要注意的另一件事是Task.GetAwaiter()返回 aTaskAwaiter但Task<TResult>.GetAwaiter()返回 a TaskAwaiter<TResult>。兩者沒有太大區(qū)別,只是GetResult()兩個任務(wù)的方法有區(qū)別;這就是在編組回正確的線程上下文時調(diào)用的內(nèi)容。在TaskAwaiter.GetResult()返回void和TaskAwaiter<TResult>.GetResult()回報TResult。


我覺得如果我進一步深入研究,我將不得不寫幾頁來詳細解釋這一切......希望只是解釋你的問題并稍微拉開帷幕就會有足夠的光線來幫助你理解和深入挖掘如果你更好奇。


好的,所以根據(jù)下面的評論,我想進一步描述我的答案。


我會從這個簡單的開始;讓我們做一個Task;一個沒有運行的,先看看它。


public Task GetTask()

{

    var task = new Task(() => { /*some work to be done*/ });

    //Now we have a reference to a non-running task.

    return task;

}

我們現(xiàn)在可以調(diào)用如下代碼:


public async void DoWork()

{

    await GetTask();

}

……但我們會永遠等待;直到應(yīng)用程序結(jié)束,因為Task從未啟動。然而; 我們可以這樣做:


public async void DoWork()

{

    var task = GetTask();

    task.Start();

    await task;

}

...它將等待運行Task并在Task完成后繼續(xù)。


知道了這一點,您可以根據(jù)需要進行任意數(shù)量的調(diào)用,GetTask()并且只會引用Task尚未啟動的 s。


在您的代碼中正好相反,這很好,因為這是最常用的方式。我鼓勵您確保您的方法名稱通知用戶您如何返回Task. 如果Task已經(jīng)在運行,最常見的約定是方法名稱以 結(jié)尾Async。Task為了清楚起見,這是另一個通過跑步來做的例子。


public Task DoTaskAsync()

{

    var task = Task.Run(() => { /*some work to be done*/ });

    //Now we have a reference to a task that's already running.

    return task;

}

現(xiàn)在我們很可能會像這樣調(diào)用這個方法:


public async void DoWork()

{

    await DoTaskAsync();

}

然而; 請注意,如果我們只是想像Task我們之前所做的那樣引用,我們可以,唯一的區(qū)別是這Task是在先前沒有的地方運行。所以這個代碼是有效的。


public async void DoWork()

{

    var task = DoTaskAsync();

    await task;

}

最大的收獲是 C# 如何處理 async / await 關(guān)鍵字。 async告訴編譯器該方法將成為Task. 簡而言之; 編譯器知道查找所有await調(diào)用并將方法的其余部分放在延續(xù)中。


的await關(guān)鍵字告訴編譯器調(diào)用Task.GetAwaiter()上的方法Task(和基本上訂閱INotifyCompletion和ICriticalNotifyCompletion)轉(zhuǎn)換成信號的方法中的延續(xù)。


我想補充一點,以防萬一你不知道。如果您確實有多個任務(wù)要等待,但寧愿等待一項任務(wù),就好像它們都是一項任務(wù)一樣,那么您可以使用Task.WhenAll()So 來代替:


var taskA = DoTaskAsync();

var taskB = DoTaskAsync();

var taskC = DoTaskAsync();


await taskA;

await taskB;

await taskC;

你可以像這樣寫得更干凈一點:


var taskA = DoTaskAsync(); 

var taskB = DoTaskAsync(); 

var taskC = DoTaskAsync();


await Task.WhenAll(taskA, taskB, taskC);

并且內(nèi)置了更多的方法來做這種事情;只是探索它。


查看完整回答
反對 回復(fù) 2021-11-21
  • 1 回答
  • 0 關(guān)注
  • 200 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號