StateHasChanged()与Blazor中的InvokeAsync(StateHasChanged)

StateHasChanged()与Blazor中的InvokeAsync(StateHasChanged),blazor,blazor-server-side,blazor-webassembly,Blazor,Blazor Server Side,Blazor Webassembly,我知道调用statehaschange()方法会通知组件状态已更改,应该重新呈现 然而,我在其他人的代码中也看到了对await InvokeAsync(statehaschange)或await InvokeAsync(()=>statehaschange())的调用,但我不太明白它与statehaschange()有什么不同,应该在哪里选择,为什么 我能找到的唯一信息是,上面写着: 如果必须根据外部事件(如计时器或其他通知)更新组件,请使用InvokeAsync方法,该方法将调度到Blazor

我知道调用
statehaschange()
方法会通知组件状态已更改,应该重新呈现

然而,我在其他人的代码中也看到了对
await InvokeAsync(statehaschange)
await InvokeAsync(()=>statehaschange())
的调用,但我不太明白它与
statehaschange()
有什么不同,应该在哪里选择,为什么

我能找到的唯一信息是,上面写着:

如果必须根据外部事件(如计时器或其他通知)更新组件,请使用InvokeAsync方法,该方法将调度到Blazor的同步上下文

我不太明白。它只是说“…发送到Blazor的同步上下文”,但我对此不太满意!什么是“Blazor的同步上下文”

我已尝试在
计时器的
已过
事件中调用
statehaschange()
,而不是
InvokeAsync(statehaschange)
,它按预期工作,没有任何问题。我应该调用
等待InvokeAsync(StateHasChanged)
吗?!如果是这样,为什么确切地说是这样?我觉得这里可能有一些我不知道的重要细微差别

我也看到过类似于
InvokeAsync(()=>InvokeAsync(Something))
的调用,为什么

另外,我有时还会看到调用
InvokeAsync()
时没有
wait
,这是怎么回事

我已经尝试在计时器的已用事件中调用StateHasChanged(),而不是调用InvokeAsync(StateHasChanged),它可以按预期工作

那一定是在WebAssembly上。当您在Blazor服务器端尝试此操作时,我预计会出现异常。StateHasChanged()检查它是否在正确的线程上运行

核心问题是呈现和调用状态都必须在主(UI)线程上发生更改。DOM的卷影副本不是线程安全的

Blazor的主要生命周期事件(OnInit、AfterRender、ButtonClick)都是在该特殊线程上执行的,因此在极少数情况下,您需要StateHasChanged()在那里,可以在不调用InvokeAsync()的情况下调用它

计时器是不同的,它是一个“外部事件”,因此您不能确定它是否会在正确的线程上执行。InvokeAsync()将工作委托给Blazor的SynchronizationContext,后者将确保它在主线程上运行

但是Blazor WebAssembly只有一个线程,因此目前外部事件也总是在主线程上运行。这意味着当你把这个调用模式弄错的时候,你不会注意到任何东西。直到有一天,当Blazor Wasm最终获得真正的线程时,您的代码才会失败。就像你的计时器实验一样

什么是“Blazor的同步上下文”

在.net中,同步上下文确定(在)等待后发生什么。不同的平台有不同的设置,Blazor synccontext与WinForms和WPF非常相似。默认值主要是
。ConfigureAwait(true)
:在同一线程上恢复

我有时会在顶级Blazor Wasm代码中看到
.ConfigureAwait(false)
。当我们得到真正的线索时,它也会爆炸。可以在blazor调用的服务中使用,但不能用于顶级方法

最后,
await InvokeAsync(statehaschange)
await InvokeAsync(()=>statehaschange()
只是C#中的lambda,与Blazor无关。第一个简短形式更有效

我有时还会看到调用
InvokeAsync()
时没有
wait


这绝不是一个好主意,尽管它通常会工作。但它比将调用方法(如计时器的OnTick)设置为
异步void
要好,所以请从同步代码中使用它。

谢谢。顺便说一下,关于您的语句
,最后是wait InvokeAsync(StateHasChanged或wait InvokeAsync(()=>StateHasChanged()在C#中几乎是lambda的,与Blazor无关。
但我的意思是我实际上在另一个调用中看到了一个
InvokeAsync
调用,如(第42行)嗯,这是一个测试,不确定它是用来做什么的。它不是“真正的代码”。哦,好吧,很高兴知道。谢谢!还有一件事:你声明了
…直到有一天,当Blazor Wasm最终获得真正的线程时,你的代码将失败,这是真的来了吗?还是Blazor WebAssembly希望始终保持单线程?这反过来意味着de>InvokeAsync
在Blazor WebAssembly中始终实际上是无关的,并且只在Blazor服务器端相关。我认为这正在讨论中:好的,所以还没有决定。谢谢!