-
Notifications
You must be signed in to change notification settings - Fork 10.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tasks returned from JSRuntime.InvokeAsync during OnInitAsync never finishes in preview3 #8274
Comments
I just switched an existing app which worked fine to the new version and got the same problem: Is there a workaround or did I do something fundamentally wrong? (which I don't believe because the same app worked since Blazor 0.3 and did every version upgrade, got converted to server side Razor Components weeks ago.) |
Same probleme here - the await for JSRuntime.InvokeAsync() in an component's OnInitAsync() does block forever. |
I migrated my code to preview 3 and I also ran into this problem. |
Does anybody has news / a workaround for this issue? |
@javiercn, can you please look into this? Thanks! |
I also got that problem. Anything worked fine before. |
I have hacked around it by wrapping wrapping the router component in an In App.razor, delay loading the router until we have received a message from the client @if (Started)
{
<Router AppAssembly="typeof(Startup).Assembly" />
}
else
{
<text>Waiting for Asp.Net Core 3.0 Preview3 Workaround...</text>
}
@functions {
bool Started = false;
[JSInvokable]
public void Start()
{
Started = true;
StateHasChanged();
}
protected override void OnInit()
{
_ = JSRuntime.InvokeAsync<object>("StartMe", new DotNetObjectRef(this));
}
} And adding window.StartMe to index.cshtml, calling back to the App component <script>
window.StartMe = function (dotnetHelper) {
dotnetHelper.invokeMethodAsync('Start');
}
</script> |
Not only does this happen on |
I've confirmed that it happens on all of the lifecycle events; the task never returns. |
@Honkmother I'm afraid that using any JS interop is not allowed in prerendering. (not related to the bug though) |
I am not calling it during prerendering. https://github.com/SQL-MisterMagoo/PreRenderComponent allows us to detect when the prerendering is active and avoid making JS Interop calls during it. |
@kvantetore I found an alternative work-around. It would appear if you call the InvokeAsync inside of the body of a component rather than the lifecycle methods it gets properly executed. I don't know exactly when it is executed, but I imagine it is right prior to OnAfterRender. ex. at the end of Component.razor, prior to
|
@javiercn can you please confirm whether this is fixed already? |
@mkArtakMSFT It is not. |
Jus to add we see the issue as well. The javascript methods below just do console.log. When we use await the second method does not run but if we remove the await then they both run. In our LayoutMain.cshtml file
|
Actually the right fix might just be to guarantee we never pause the SignalR message loop. |
Since we have our own sync context I agree with all of the above. The reason to pause the message loop is to guarantee ordering. We implement ordering ourselves. |
I was going to comment on this but I was on vacation 😄. Sorry you had to spend your time investigating this @SteveSandersonMS. There's an issue in SignalR to allow a maximum number of concurrent invocations (it should really be more than 1), that should help solve this issue. |
Agree. It should not wait at all, and deal with errors in the way we do in other places. We should just wrap the task to get notified and that's it. Once StartCircuit has been called the connection must be up and running already so UpdateDisplay should work just fine. |
If this is important for Razor Components, please let us know so we can prioritize appropriately. |
Turns out that in general we don't block the SignalR message loop. In all cases except one we just hand off to the circuit's dispatcher and the call is synchronous from SignalR's perspective. The one bad case was |
@davidfowl Thanks for the info. I wasn't regarding this as a SignalR issue since, even if SignalR did allow concurrent hub method invocations, we'd have had a different problem where you could have received incoming JSInterop calls before the circuit was flagged as started. The underlying false assumption is now fixed in #8863 so neither problem occurs. Totally agree it would be good for SignalR to have the flexibility to handle parallel messages in general though. |
Has this been fixed yet? This returns a Task that never ends: This does not return at all, no matter where I call it from. Unless I am missing something, this means I can't get results back from JavaScript at all. |
Actually to understand what happen when trying to launch a task on Blazor you should understand JavaScript execution lifecycle. To sum up, any task in a JavaScript environment in the context of the browser (Safari, Chrome , Edge, ...) cannot be executed when the current task is running. That means you are dead locking when trying to wait the initiated task by JSRuntime.InvokeAsync<...>(“functionName”,...).AsTask().Wait() in a “synchronous” Blazor function. The solution is to always perform those task calls in an async containing function and call StateIsChanged() function to say to the browser that the model was updated and that it should refresh the DOM |
I got the same problem calling Google Maps API in component's Dispose method (I need to remove markers on map). I solved the problem setting limit of waiting time:
Error occurs after Refresh page (F5). There is no workaround thus I had to hide it. |
Doesn't Blazor support IAsyncDisposable? Task.WaitAll feels so aged. |
This method is called from Dispose: I need to call GooleMapsAPI for removing markers and paths from map. All works fine except page refresh (F5). Do you know another way? Please tell it me. |
|
And where is problem? One can use any operator or expression unless it
marked with 'obsolete'. It would be very strange if someone will state that
'foreach' is too old and only asynchronous version of the operator is
legal. I proposed the solution write your one if it works better.
2019-12-17, an, 16:17 Sören Nils Kuklau <notifications@github.com> rašė:
… Doesn't Blazor support IAsyncDisposable? Task.WaitAll feels so aged.
Not yet. <#9960>
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#8274>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AADHFL7LLUAJEUOKOOM6R73QZDNPFANCNFSM4G4LVJMQ>
.
--
Gediminas Bukauskas
SKYPE: gediminasbuk
Phone: +370 37 793622
Mobile: +370 611 31090
E-mail: gbukauskas@gmail.com
|
Hi, it looks like you are posting on a closed issue/PR/commit! We're very likely to lose track of your bug/feedback/question unless you:
Thanks! |
Describe the bug
Tasks returned from JSRuntime.InvokeAsync during second call to OnInitAsync (after prerendering) never finishes.
To Reproduce
Create a new razorcomponents project.
Add a js interop function to Index.cshtml and disable prerendering
Call js interop during OnAsyncInit in Index.razor
When OnInitAsync is called as part of an initial load (prerendering disabled) the task never finishes, This leaves the circuit hanging, and no further events are processed.
If this component is loaded from a
IUriHelper.OnLocationChange
, the above code works as expected.The text was updated successfully, but these errors were encountered: