怎么任务。产率工作的发动机罩下在Blazor WebAssembly?

0

的问题

如何 Task.Yield 工作罩下在 单/WASM运行时 (这是由Blazor WebAssembly)?

为了澄清,我相信我有一个很好的理解 如何 Task.Yield 工作 中。净框架。净的核心。 单实施 看起来并不太大的不同,概括地说,它涉及到这个:

static Task Yield() 
{
    var tcs = new TaskCompletionSource<bool>();
    System.Threading.ThreadPool.QueueUserWorkItem(_ => tcs.TrySetResult(true));
    return tcs.Task;
}

令人惊讶的是,这一工作在Blazor WebAssembly,太(尝试在线):

<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();
        }
    }
}

当然,这一切都发生在同一事件循环线浏览器,所以我不知道它是如何工作在较低的水平。

我怀疑,它可能是利用喜欢的东西 Emscripten的Asyncify,但最终,它是否使用某种形式的网络平台API要安排延续回? 如果是,哪一个正(喜欢 queueMicrotask, setTimout, Promise.resove().then等)?


更新,我刚发现 Thread.Sleep 实现,以及它实际上 块的事件循环线

.net async-await blazor c#
2021-11-24 06:13:47
1

最好的答案

5

它的 setTimeout. 有相当多的间接之间,以及 QueueUserWorkItem但这是它的底部。

大多数WebAssembly特定的机械可以看出,在 公关38029. 该WebAssembly执行情况 RequestWorkerThread 呼叫一个私人的命名方法 QueueCallback,这是实现C码 mono_wasm_queue_tp_cb. 这在调用 mono_threads_schedule_background_job,这反过来通话 schedule_background_exec,这是实施稿为:

export function schedule_background_exec(): void {
    ++pump_count;
    if (typeof globalThis.setTimeout === "function") {
        globalThis.setTimeout(pump_message, 0);
    }
}

setTimeout 回最终到达 ThreadPool.Callback,其调用 ThreadPoolWorkQueue.Dispatch.

其余的就不是特定于Blazor在所有,并可以研究通过阅读的源代码 ThreadPoolWorkQueue 类。 在短短的, ThreadPool.QueueUserWorkItem 入队回调一个 ThreadPoolQueue. 入队的呼叫 EnsureThreadRequested,这代表 RequestWorkerThread实现如上。 ThreadPoolWorkQueue.Dispatch 导致一些数量的异步的任务是出队和执行;其中,回过来 QueueUserWorkItem 应该最终会出现。

2021-11-28 11:17:30

一个伟大的回答,公司! 但geven它的 setTimeout你能解释一个巨大的差异,我看到了当时的一个循环 await new Promise(r => setTimeout(r, 0)) 与JS互操作vs的一个循环 await Task.Yield? 是有缺陷的测试? blazorrepl.telerik.com/QlFFQLPF08dkYRbm30
noseratio

queueMicrotask (而不是 setTimeout)产生一个更近的结果: blazorrepl.telerik.com/QFbFGVFP10NWGSam57
noseratio

我无法打开任何REPL链接,所以我不能告诉你是什么意思。 但是如果你的研究的源代码 ThreadPoolWorkQueue.Dispatch你会注意到有一些复杂的调度涉及以及一个 setTimeout 可能为多个排队。净步的任务,我希望将快于具有每 setTimeout 派遣一个单一的回调。
user3840170

奇repl链接不工作。 如果你还是想试试,这里的要点: gist.github.com/noseratio/73f6cd2fb328387ace2a7761f0b0dadc. 这是literrally8000ms vs20毫. 然后就换 setTimeoutqueueMicrotask,这是关于相同的20毫.
noseratio

似乎是它: setTimeout 让浏览器进程的事件循环之间的回调,但是的.净运行时能够派遣多个异步的任务在一个单一的 setTimeout callback(出列它们几乎立刻后他们排队),从而避免的开销产生的事件循环。 (此外,浏览器可以执行限制 setTimeout 呼吁,这本批处理避免了.) 这产生的一个影响大约相当于 queueMicrotask. 虽然时间你都可能不是非常精确,由于恐惧的缓解措施。
user3840170

其他语言

此页面有其他语言版本

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................