當我注意到一些我無法解釋的行為時,我正在 Unity 中玩異步任務。在控制臺上列印一些值以查看發生了什么時,我注意到我正在玩的各種場景的執行緒 ID。下面的代碼包括以下內容:
- “一勞永逸”的異步 void 中的兩個測驗讓一??切順利進行
- 一個任務等待另一個任務(一個小的延遲)
- 以及一些除錯日志來監控每個啟動任務的執行緒 ID
Start 方法中的TEST 1只是等待 SimpleTask 并給出以下輸出:
任務開始于執行緒:1
執行緒延遲前的 SimpleTask:1
執行緒上的 SimpleDelay:1
執行緒延遲后的 SimpleTask:1
另一方面,TEST 2導致了這一點:
任務開始于執行緒:1
執行緒延遲前的 SimpleTask:25
執行緒上的 SimpleDelay:25
執行緒延遲后的 SimpleTask:26
為什么第二次測驗導致使用其他執行緒? 我對這一行的理解是,它只是將第一個測驗包裝在異步任務的額外層中。我知道這樣做沒有意義,但我不明白為什么它會完全改變初始測驗的結果。這不像第一個測驗是同步運行的。我想了解這里發生了什么,解釋越多越好。
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
public class TestAsyncTask : MonoBehaviour
{
private async void Start()
{
Debug.Log($"Task started on thread: {Thread.CurrentThread.ManagedThreadId}");
// TEST 1
await SimpleTaskAsync();
// TEST 2
await Task.Factory.StartNew(async () => await SimpleTaskAsync());
}
private async Task SimpleTaskAsync()
{
Debug.Log($"SimpleTask before delay on thread: {Thread.CurrentThread.ManagedThreadId}");
await SimpleDelayAsync();
Debug.Log($"SimpleTask after delay on thread: {Thread.CurrentThread.ManagedThreadId}");
}
private async Task SimpleDelayAsync()
{
Debug.Log($"SimpleDelay on thread: {Thread.CurrentThread.ManagedThreadId}");
await Task.Delay(1000);
}
}
其他規格(我懷疑它們很重要,但無論如何都是這樣):
- Unity 版本 2021.3.11f1
- API 兼容級別:.NET Framework
uj5u.com熱心網友回復:
await默認情況下將捕獲當前背景關系(SynchronizationContext或TaskScheduler)并async在該背景關系中繼續執行該方法;如果沒有背景關系,那么它們將在執行緒池執行緒上運行。我建議您閱讀我的async介紹,其中更詳細。
在這種情況下,我假設代碼在 UI 背景關系中執行(在 UI 執行緒上)。UI 框架在 UI 執行緒上恢復SynchronizationContext之后提供了一個這樣的代碼。await
我對這一行的理解是,它只是將第一個測驗包裝在異步任務的額外層中。
第二個代碼不使用 UI 執行緒的原因是StartNew(正如我在博客中所描述的那樣,它很危險;請Task.Run改用)。Task.Run總是在執行緒池執行緒上執行它的委托,并且StartNew(在這種情況下)也這樣做。執行緒池執行緒沒有任何await要捕獲的背景關系,因此await在任何可用執行緒池執行緒上運行之后的代碼。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/511436.html
下一篇:科特林。運行時錯誤:執行緒“main”中的例外java.lang.IndexOutOfBoundsException:索引:1,大小:1
