Come si fa Task.Yield
lavorare sotto il cofano in Mono/WASM runtime (che è utilizzato da Blazor WebAssembly)?
Per chiarire, credo di avere una buona comprensione di come Task.Yield
funziona in .NET Framework e .NET Core. Mono attuazione , non ha un aspetto molto diverso, in sintesi, si tratta di questo:
static Task Yield()
{
var tcs = new TaskCompletionSource<bool>();
System.Threading.ThreadPool.QueueUserWorkItem(_ => tcs.TrySetResult(true));
return tcs.Task;
}
Sorprendentemente, questo funziona in Blazor WebAssembly ancheprovare on-line):
<label>Tick Count: @tickCount</label><br>
@code
{
int tickCount = System.Environment.TickCount;
protected override void OnAfterRender(bool firstRender)
{
if (firstRender) CountAsync();
}
static Task Yield()
{
var tcs = new TaskCompletionSource<bool>();
System.Threading.ThreadPool.QueueUserWorkItem(_ => tcs.TrySetResult(true));
return tcs.Task;
}
async void CountAsync()
{
for (var i = 0; i < 10000; i++)
{
await Yield();
tickCount = System.Environment.TickCount;
StateHasChanged();
}
}
}
Naturalmente, tutto questo accade nello stesso ciclo di eventi thread nel browser, quindi mi chiedo come funziona al livello inferiore.
Ho il sospetto, si potrebbe essere utilizzando qualcosa come Emscripten del Asyncify, ma alla fine, fa uso di una sorta di Web API della Piattaforma per pianificare una continuazione di callback? E se sì, quale esattamente (come queueMicrotask
, setTimout
, Promise.resove().then
, etc)?
Aggiornamento, ho appena scoperto che Thread.Sleep
è implementato come bene e in realtà blocca il ciclo di eventi del thread
setTimeout
potresti spiegare un enorme discrepanza sto vedendo quando l'intervallo di un ciclo diawait new Promise(r => setTimeout(r, 0))
con JS interoperabilità vs un ciclo diawait Task.Yield
? C'è un difetto nel test? blazorrepl.telerik.com/QlFFQLPF08dkYRbm30