如何解决“当前线程未与渲染器的同步上下文关联”的问题?

时间:2019-06-06 12:41:09

标签: c# asp.net-core blazor .net-core-3.0 blazor-server-side

我试图在blazor服务器端应用程序中更改用于标题的字符串。但是我无法更新用户界面。

我尝试使用StateHasChanged(),但是没有用,所以我环顾四周,发现在制作的FlightFinder演示中,它具有OnChange事件Action,因此我正在尝试实现它。

在我尝试刷新浏览器之前,它一直有效,然后我被这个错误击中

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调用方法在正确的线程上? 还是有另一种更改标题的方法更有效?

提前谢谢!

3 个答案:

答案 0 :(得分:19)

我刚刚实现了这样的状态容器,并遇到了相同的错误-但我的服务需要是单例。 因此,我在aspnetcore git上找到了一个示例,该示例完全执行错误消息说明的操作。 呼叫 InvokeAsync -不是从状态容器中调用,而是在您尝试更改剃刀组件的状态时调用。

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)
    {
        DoStuff();
        // InvokeAsync is inherited, it syncs the call back to the render thread
        await InvokeAsync(() => StateHasChanged());
    }
}

现在,您的服务(如果是单身人士)可以立即通知所有您的用户!考虑一下过去我们要做的所有事情。

答案 1 :(得分:3)

我在早上发布了第一件事,以为我没有时间去研究,并以为只要有人能够帮助我,我就会有时间去研究它。尽管我已经花了几天来回的时间。

我终于找到this article,这说明我试图做的事情叫做状态容器。

他们说的是,我可以将类作为单例注入,这就是我正在做的事情或作用域服务。原来我要做的就是将其更改为有范围的服务,并且效果很好!

答案 2 :(得分:-2)

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

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