How external async operation completion is implemented in Blazor WebAssembly?

Viewed 160

I'm looking for a high-level description of how external async operation completion is implemented in Blazor WebAssembly, and I'm mostly interested in how it works for timers (Task.Delay, etc.) and JS interop.

I know Blazor WASM is single-threaded, so there must be some event loop, or it might be even JS event loop that calls WASM code, which temporarily activates WASM event loop / .NET thread pool event loop. The question, though, is: what happens once .NET thread pool work item queue gets empty - i.e. there are no more tasks to continue right now, but they're expected to pop up in future (due to timers & JS interop calls)? Some of the options I see are:

  • Continue spinning in .NET / WASM & polling a shared buffer through which JS-to-.NET calls are marshalled; once there is a new call entry, transform it into a work item & run while you can; rinse & repeat after that. The downside of this approach is pretty high CPU consumption: basically, there is no notion for "temp. pausing a thread that await for IO completion" here.
  • Returning the control back to JS code & stop executing .NET Code. This option implies that such things as timers & IO are all pass through JS interop. No problem with high CPU consumption here, but the cost of having a timer or awaiting for IO completion might be higher in this case.
  • A mix of these options. E.g. .NET thread pool code might decide to retain the control to wait for timers that are almost ready to trigger, but release the control to JS if there are none of such timers.

Overall, I'd like to know how this actually works. High-level description is more than enough, though if you don't have much time to write it, links to the source code are fine as well.

0 Answers
Related