如何修复“当前线程未与渲染器的同步上下文相关联”?
How to fix 'The current thread is not associated with the renderer's synchronization context'?
我正在尝试更改我的 blazor-server-side 应用程序中用于标题的字符串。但是我无法更新 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("some Page Title") 并且它有效,除非像我提到的那样我尝试刷新。
我只是想通过另一个组件更改一个组件上的字符串,这听起来并不那么疯狂。如果有更好的方法来制作标题或更改其他组件的东西,我很想听听。
那么,我该怎么做才能确保 m invoke 方法在正确的线程上?
或者是否有其他更有效的更改标题的方法?
提前致谢!
我在早上发布了第一件事,当时我想我没有时间去研究,并且认为当有人能够帮助我时,我会抽出时间来研究它。虽然我已经花了几天时间来回讨论这个问题。
我终于找到 this article 解释我正在尝试做的事情叫做状态容器。
他们说我可以将 class 作为单例注入,这就是我正在做的或范围内的服务。事实证明,我需要做的就是将其更改为范围内的服务,而且效果很好!
我刚刚实现了一个像这样的状态容器并且 运行 出现了同样的错误 - 但我的服务 需要 是一个单例。
所以我在 aspnetcore git 上找到了一个示例,它完全按照错误消息所说的去做。
调用 InvokeAsync -- 不是从您的状态容器调用,而是在您尝试更改剃刀组件的状态时调用。
因此您的状态容器不需要更改,只需更改您的组件事件处理程序即可。
@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());
我正在尝试更改我的 blazor-server-side 应用程序中用于标题的字符串。但是我无法更新 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("some Page Title") 并且它有效,除非像我提到的那样我尝试刷新。
我只是想通过另一个组件更改一个组件上的字符串,这听起来并不那么疯狂。如果有更好的方法来制作标题或更改其他组件的东西,我很想听听。
那么,我该怎么做才能确保 m invoke 方法在正确的线程上? 或者是否有其他更有效的更改标题的方法?
提前致谢!
我在早上发布了第一件事,当时我想我没有时间去研究,并且认为当有人能够帮助我时,我会抽出时间来研究它。虽然我已经花了几天时间来回讨论这个问题。
我终于找到 this article 解释我正在尝试做的事情叫做状态容器。
他们说我可以将 class 作为单例注入,这就是我正在做的或范围内的服务。事实证明,我需要做的就是将其更改为范围内的服务,而且效果很好!
我刚刚实现了一个像这样的状态容器并且 运行 出现了同样的错误 - 但我的服务 需要 是一个单例。 所以我在 aspnetcore git 上找到了一个示例,它完全按照错误消息所说的去做。 调用 InvokeAsync -- 不是从您的状态容器调用,而是在您尝试更改剃刀组件的状态时调用。
因此您的状态容器不需要更改,只需更改您的组件事件处理程序即可。
@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());