如何修复"当前线程与渲染器的同步上下文不关联"?



我正在尝试在我的 blazor 服务器端应用程序中更改用于标题的字符串。但是我在更新 UI 时遇到问题。

我尝试使用StateHasChanged(),但这不起作用,所以我环顾四周,发现在制作的FlightFinder演示中,它有一个OnChange事件操作,所以我正在尝试实现它。

它一直有效,直到我尝试刷新浏览器,然后我遇到此错误

System.InvalidOperationException:"当前线程未与渲染器的同步上下文关联。使用 Invoke() 或 InvokeAsync() 在触发渲染或修改渲染期间访问的任何状态时,将执行切换到渲染器的同步上下文。

这是我所拥有的:

private string _title = "TestSite";
public string Title => _title;
public event Action OnChange;
public void ChangePage(string pageName)
{
_title = pageName;
NotifyStateChanged();
}
private void NotifyStateChanged(int navigationType = 0)
{
OnChange?.Invoke();
}

我所要做的就是调用ChangePage("一些页面标题")并且它可以工作,除非我提到我尝试刷新。

我只是想通过另一个组件更改一个组件上的字符串,这听起来并不那么疯狂。如果有更好的方法来制作标题或更改其他组件的内容,我很想听听。

那么,我该怎么做才能确保 m invoke 方法在正确的线程上呢? 还是有没有其他方法可以更有效地更改标题?

提前谢谢你!

我刚刚实现了这样的状态容器并遇到了同样的错误 - 但我的服务需要是一个单例。 所以我在 aspnetcore git 上找到了一个示例,它完全按照错误消息所说的方式执行。 调用InvokeAsync- 不是从状态容器,而是在尝试更改 razor 组件的状态时调用。

https://github.com/dotnet/aspnetcore/blob/321db9d99f84cf7a67d453384292d9339de748d1/src/Components/test/testassets/BasicTestApp/DispatchingComponent.razor

因此,状态容器不需要更改,只需更改组件事件处理程序即可。

@code{
protected override void OnInitialized()
{
_YourService.OnChange += OnMyChangeHandler;
}
public void Dispose()
{
_YourService.OnChange -= OnMyChangeHandler;
}
private async void OnMyChangeHandler(object sender, EventArgs e)
{
// InvokeAsync is inherited, it syncs the call back to the render thread
await InvokeAsync(() => {
DoStuff();
StateHasChanged();
});
}
}

现在,您的服务(如果是单例)可以立即通知所有用户!想想我们过去必须跳过的所有箍来做到这一点。

我早上发布了第一件事,认为我没有时间去研究,并认为当有人能够帮助我时,我会找到时间更多地研究它。虽然我已经花了几天时间来回讨论这个问题。

我终于找到了这篇文章,它解释了我正在尝试做的事情被称为状态容器。

他们说我可以将类作为单例注入,这就是我正在做的事情或作用域服务。事实证明,我需要做的就是将其更改为范围服务,它工作得很好!

不需要复杂的解决方案,如果您通过以下方式更新事件处理程序中的 GUI,Blazor 可以完美运行

this.InvokeAsync(() => this.StateHasChanged());

在我的情况下使用await InvokeAsync(stateHasChanged);

最新更新