Aspnetcore: Task to StateHasChanged = RemoteRendererException | Blazor 0.8.0

Created on 19 Feb 2019  路  5Comments  路  Source: dotnet/aspnetcore

Hello, in Blazor 0.8.0, you cannot call StateHasChanged() from another thread, but before 0.8.0 everything worked.

Example:

Task.Run(() => StateHasChanged());

Error:

Microsoft.AspNetCore.Components.Browser.Rendering.RemoteRendererException: "The current thread is not associated with the renderer's synchronization context. Use Invoke() or InvokeAsync() to switch execution to the renderer's synchronization context when triggering rendering or modifying any state accessed during rendering."
area-blazor question

Most helpful comment

@cores-system you should be able to change

StateHasChanged(); in your code to base.Invoke(StateHasChanged); so it becomes

protected override void OnInit()
{
    WebApplication7703.Shared.CliEventTo.OnRequest += (ip) =>
    {
        IPs += ip + "<br />";

        base.Invoke(StateHasChanged);
    };

    base.OnInit();
}

I pulled your example and tried it out and "it works on my machine" 馃槈

All 5 comments

@cores-system the exception appears to be from a Components (server-side rendered) application and not a Blazor app. Could you confirm this to be the case? If so, the error is entirely intentional in a Components app and the message includes the change you'd have to make in your application to fix it.

@pranavkm, Yes, this (server-side rendered).
I understand that I need to execute StateHasChanged() in the application stream, but I do not understand how I will switch to it while in the Mvc stream.

Example application:
https://github.com/cores-system/WebApplication7703

@cores-system you should be able to change

StateHasChanged(); in your code to base.Invoke(StateHasChanged); so it becomes

protected override void OnInit()
{
    WebApplication7703.Shared.CliEventTo.OnRequest += (ip) =>
    {
        IPs += ip + "<br />";

        base.Invoke(StateHasChanged);
    };

    base.OnInit();
}

I pulled your example and tried it out and "it works on my machine" 馃槈

@christiansparre, Thanks, it really works ))

IT REALLY DOES WORK. 馃榿

Trying Blazor out and ran into this problem, which led me to this issue.

From my modified Counter.razor using the default server-side template (trying to simulate a busy screen):

<button class="btn btn-primary" onclick="@IncrementCount" disabled="@(!enabled)">Click me</button>

@functions {
    bool enabled = true;
    int currentCount;

    Task IncrementCount(UIMouseEventArgs sender)
        => Task.Run(() =>
                    {
                        enabled = false;
                        return currentCount++;
                    })
               .ContinueWith(_ => Task.Delay(1000))
               .Unwrap()
               .ContinueWith(_ =>
                             {
                                 Invoke(StateHasChanged);
                                 enabled = true;
                                 return currentCount--;
                             });

And it (now) works! So very cool! Nice work all around there to the entire team. 馃憤

Was this page helpful?
0 / 5 - 0 ratings