Blazor 有“UI 线程”吗?

Dav*_*len 2 blazor blazor-server-side

我以前的编程是 Windows 窗体,其中有一个 UI 线程,任何涉及 UI 的代码都必须在该线程中调用。一旦你掌握了它的窍门,这不是一个大问题,但你必须小心地始终调用该线程。

Blazor(服务器端)有相同的概念吗?我猜不会,因为无论线程如何,所有东西都将某些东西推入电路,然后该电路在客户端成为单个线程。

但我觉得还是问一下比较好。从哪些线程调用哪些代码有任何限制吗?


以及附加的后续问题。我接到的每个电话都OnInitializedAsync在该 UI 线程中 - 对吗?我从 Blazor 和 DevExpress 组件实现了所有这些异步事件。虽然它们都是异步的,但它们都在主 UI 线程中 - 对吗?

这意味着如果我创建后台线程或计时器,我只需关心这一点。(在 WinForms 的情况下,当您收到事件/回调时,您经常处于非 UI 线程中。)

MrC*_*tis 5

Blazor Hub 中的每个服务器端会话都相当于一个称为Synchronisation Context. 将其视为虚拟线程。

直接引用本文档 - https://github.com/dotnet/AspNetCore.Docs/blob/main/aspnetcore/blazor/components/synchronization-context.md

Blazor 使用同步上下文 (System.Threading.SynchronizationContext) 来强制执行单个逻辑线程。Blazor 引发的组件的生命周期方法和事件回调在同步上下文上执行。

Blazor Server 的同步上下文尝试模拟单线程环境,以便它与浏览器中的单线程 WebAssembly 模型紧密匹配。在任何给定时间点,工作都在一个线程上执行,这会产生单个逻辑线程的印象。没有两个操作同时执行。

鉴于此,如果您需要在 Blazor Server 中,没有什么可以阻止您将一些处理器密集型代码卸载到线程池线程。WASM 目前是单线程的,因此您无法卸载。多线程是有保证的。

一个值得注意的例外是服务器中的计时器。它们在线程池线程上运行。如果您的事件处理程序调用,StateHasChanged您需要调用InvokeAsync(StateHasChanged)将其切换回同步上下文。

ComponentBase方法如下所示:

protected Task InvokeAsync(Action workItem)
    => _renderHandle.Dispatcher.InvokeAsync(workItem);
Run Code Online (Sandbox Code Playgroud)

_renderHandle.Dispatcher是对同步上下文的调度程序的引用。

因此,为此需要掌握的重要知识是:

  • 所有渲染器生成的事件 - IComponentIHandleEventIHandleAfterRenderUI 回调事件(例如按钮单击、更改事件)都在Synchronisation Context.
  • 一次仅运行一个代码块 - 没有并行处理。
  • 返回上下文允许渲染器为其队列提供服务。继续进行,渲染和 UI 生成的事件代码可以运行。