在 Blazor 中,`await Task.Run(StateHasChanged)` 和 `await InvokeAsync(StateHasChanged)` 有什么区别?

3
我最近继承了一个Blazor Webassembly应用程序,但是我对dotnet或Blazor的经验非常有限。一些组件使用await Task.Run(StateHasChanged)而不是await InvokeAsync(StateHasChanged),我想知道这是否是有意的。
我之所以问,是因为当尝试使用bUnit渲染组件时,await Task.Run(StateHasChanged);会给我以下异常:
System.InvalidOperationException当前线程未与调度程序相关联。在触发渲染或组件状态时使用InvokeAsync()将执行切换到调度程序。
将此更改为await InvokeAsync(StateHasChanged);允许在bUnit中呈现组件。但是,据我所知,无论是使用await Task.Run(StateHasChanged)还是await InvokeAsync(StateHasChanged)运行应用程序时,该组件的功能都是相同的。
调用StateHasChanged这两种方法之间有什么区别?

4
这篇文章讲解了一般情况下的区别:https://dev59.com/EFkT5IYBdhLWcg3wV-KZ 我猜想,StateHasChanged的东西遵循相同的解释,“Task.Run可能会将操作发布到不同的线程进行处理。这是唯一的区别。” - gunr2171
一位 DevOps 工程师接手了一个 Blazor 项目。祝你一切顺利! - Ayudh
当需要从非UI事件的操作中刷新UI时,需要调用InvokeAsync,这将允许将StateHasChanged发送到UI线程。当事件基于UI时,不需要这样做。Task.Run会创建一个新的上下文,它不在UI线程上。(Asp.net Core Doc on using StateHasChanged)https://learn.microsoft.com/en-us/aspnet/core/blazor/components/rendering?view=aspnetcore-6.0#when-to-call-statehaschanged - Shuryno
通过线程,我不确定我是否使用了正确的术语,更像是上下文,因为对于Blazor Wasm而言,它还不清楚是否可以处理多个线程。Webassembly似乎支持它,但并非所有浏览器都支持,或者很久以前就不支持了。因此,如果尚未支持多个线程,则使用Task.Run可能会阻塞主线程。 - Shuryno
@Shuryno:第一个评论已经可以作为一个答案了...而Task.Run()不会阻塞,它只是在主线程上执行。 - H H
显示剩余2条评论
1个回答

2
据我所知,组件的功能相同......。 是的。 Task.Run(job) 将在线程池上运行该作业。但是,在WebAssembly中没有额外的线程,主(唯一)线程迟早将必须运行此作业。
在 Blazor Server 中,您确实有线程。 Task.Run() 在那里可以工作,但是StateHasChanged() 必须在主线程上运行。这意味着
 await Task.Run(StateHasChanged)   // bug!  Don't do this.

这绝对是一个bug,无处不在。目前在WebAssembly上仍未被注意到。直到Blazor Wasm也获得线程的那一天,它才会抛出异常。

所以bUnit是正确的,修复你的代码吧。

请注意,在“正常”的生命周期事件(如OnInitialized [Async]、OnClick、OnSubmit等)中,您根本不需要使用InvokeAsync()。我通常只使用

  StateHasChanged();

在外部事件(例如定时器)或线程化代码(在服务器上)中

  await InvokeAsync(StateHasChanged);

我认为他现在遇到错误的解释和开发者没有遇到的原因可能是因为@Sam Carswell正在使用支持Wasm多线程的浏览器,而它是在没有支持该功能的浏览器上开发的。我看不出还有其他原因留下来了。 - Shuryno
1
不,错误出现在bUnit运行时,而bUnit始终在服务器端运行,因此出现了错误。据我所知,Blazor尚未在任何浏览器中支持Wasm线程。 - H H
哦,好的,是的,我错过了那个bUnit参考。好观点! :) - Shuryno
@HenkHolterman 感谢您详细的回答。我发现这两种方法之间存在一些细微差别(不确定它是故意的还是一个漏洞),但我已经在这里解释了不同的结果(链接)。 - Sam Carswell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接