gpt4 book ai didi

blazor - Blazor 中的 StateHasChanged() 与 InvokeAsync(StateHasChanged)

转载 作者:行者123 更新时间:2023-12-03 15:32:43 26 4
gpt4 key购买 nike

我知道调用StateHasChanged()方法通知组件状态已更改,因此它应该重新渲染。
但是,我也看到了对 await InvokeAsync(StateHasChanged) 的调用。或 await InvokeAsync(() => StateHasChanged())在其他人的代码中,但我不太明白它与 StateHasChanged() 有何不同以及应该在哪里选择一个而不是另一个,以及为什么。
我能找到的唯一信息是this part of the Blazor docs , 它说:

In the event a component must be updated based on an external event, such as a timer or other notifications, use the InvokeAsync method, which dispatches to Blazor's synchronization context.


我不太明白这个。它只是说“...调度到 Blazor 的同步上下文”,但我对此不太满意!什么是“Blazor 的同步上下文”?
我试过调用 StateHasChanged() - 而不是 InvokeAsync(StateHasChanged) - 在 TimerElapsed事件,它按预期工作,没有任何问题。我应该调用 await InvokeAsync(StateHasChanged)反而?!如果是这样, 为什么确切地?我觉得这里可能有一些我不知道的重要细微差别。
我也见过像 InvokeAsync(() => InvokeAsync(Something)) 这样的电话。 ,再次,为什么?
另外,我有时也会看到 InvokeAsync()未调用 await ,这有什么关系?!

最佳答案

I have tried calling StateHasChanged() - instead of InvokeAsync(StateHasChanged) - in a Timer's Elapsed event, and it works as expected


那一定是在 WebAssembly 上。当您在 Blazor Serverside 上尝试时,我预计会出现异常。 StateHasChanged() 检查它是否在正确的线程上运行。
核心问题是渲染和​​调用 StateHasChanged 都必须发生在主(UI)线程上。 DOM 的影子副本不是线程安全的。
主要的 Blazor 生命周期事件(OnInit、AfterRender、ButtonClick)都在该特殊线程上执行,因此在极少数情况下您需要 StateHasChanged() 可以在没有 InvokeAsync() 的情况下调用它。
Timer 是不同的,它是一个“外部事件”,所以你不能确定它会在正确的线程上执行。 InvokeAsync() 将工作委托(delegate)给 Blazor 的 SynchronizationContext,这将确保它确实在主线程上运行。
但是 Blazor WebAssembly 只有 1 个线程,所以暂时外部事件也总是在主线程上运行。这意味着当你把这个 Invoke 模式弄错时,你不会注意到任何事情。直到有一天,当 Blazor Wasm 最终获得真正的线程时,您的代码将失败。与您的 Timer 实验一样。

What is "Blazor's synchronization context"?


在 .net 中,同步上下文决定了(之后)等待会发生什么。不同的平台有不同的设置,Blazor synccontext 很像 WinForms 和 WPF。主要是默认 .ConfigureAwait(true) : 在同一个线程上恢复。
我有时会看到 .ConfigureAwait(false)在顶级 Blazor Wasm 代码中。当我们在那里获得真正的线程时,它也会爆炸。可以在从 blazor 调用的服务中使用,但不能用于顶级方法。
最后, await InvokeAsync(StateHasChanged)await InvokeAsync(() => StateHasChanged()只是关于 C# 中的 lambda,与 Blazor 无关。第一个简短的形式更有效一些。

I also sometimes see InvokeAsync() called without await


那可行。它可能比其他选项更好:将调用方法(如 Timer 的 OnTick)设置为 async void .所以请从同步代码路径中使用它。

关于blazor - Blazor 中的 StateHasChanged() 与 InvokeAsync(StateHasChanged),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65230621/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com