You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently, it is not possible to start fetching 2 or more byte arrays via JSInterop at once.
This is a problem as larger sites might wish to retrieve multiple byte arrays independently simultaneously.
In my use case, I do this when displaying plots of sound amplitudes in the demos of Blazor.WebAudio. Currently, it either breaks randomly if two plots try to refresh at the same time or I have to do more scheduling work to ensure that no two arrays are being fetched at the same time.
If you try out the demo you see that we get the following exception:
JSException: An exception occurred executing JS interop: JSON serialization is attempting to deserialize an unexpected byte array.. See InnerException for more details.
if(JSRuntime.ByteArraysToBeRevived.Count==0){thrownewJsonException("JSON serialization is attempting to deserialize an unexpected byte array.");}
ByteArraysToBeRevived becomes empty when another JSInterop invocation has started before the current one finishes deserializing the response as can be seen here: JSRuntime.cs#L200
/// <summary>/// Accepts the byte array data being transferred from JS to DotNet./// </summary>/// <param name="id">Identifier for the byte array being transfered.</param>/// <param name="data">Byte array to be transfered from JS.</param>protectedinternalvirtualvoidReceiveByteArray(intid,byte[]data){if(id==0){// Starting a new transfer, clear out previously stored byte arrays// in case they haven't been cleared already.ByteArraysToBeRevived.Clear();}if(id!=ByteArraysToBeRevived.Count){thrownewArgumentOutOfRangeException($"Element id '{id}' cannot be added to the byte arrays to be revived with length '{ByteArraysToBeRevived.Count}'.",innerException:null);}ByteArraysToBeRevived.Append(data);}
So the core of the problem is that all calls that return a byte array use the same ArrayBuilder<byte[]> ByteArraysToBeRevived instance.
Expected Behavior
The expected behavior is that we can do multiple JSInterop calls that return byte arrays at once.
This can be fixed by changing ByteArraysToBeRevived to be a concurrent dictionary from a long id to a byte array and then not resetting the id that we use to identify each byte array argument in a single invocation which is called nextByteArrayIndex.
This would mean that we no longer use ArrayBuilder<byte[]>, which was smart as Blazor would then automatically throw away any references to byte arrays that didn't end up being deserialized. To get around this we would need to ensure that we also "release" or "return" those arrays that we didn't end up deserializing.
I would love to supply and collaborate on a PR for fixing this.
Unrelated:
There currently is an unrelated bug that we don't clear ByteArraysToBeRevived when a JSInterop task is canceled. The problem is negated by the JSInterop code pessimistically clearing it anyway when making a new call that returns a byte array (or more). Which is probably why that has not been reported previously.
JSException: An exception occurred executing JS interop: JSON serialization is attempting to deserialize an unexpected byte array.. See InnerException for more details.
Is there an existing issue for this?
Describe the bug
Currently, it is not possible to start fetching 2 or more byte arrays via JSInterop at once.
This is a problem as larger sites might wish to retrieve multiple byte arrays independently simultaneously.
In my use case, I do this when displaying plots of sound amplitudes in the demos of Blazor.WebAudio. Currently, it either breaks randomly if two plots try to refresh at the same time or I have to do more scheduling work to ensure that no two arrays are being fetched at the same time.
I have a minimal sample of this bug in this repo: https://github.com/KristofferStrube/BlazorFailsToDeserializeTwoByteArraysAtOnce
Which can be demoed live here: https://kristofferstrube.github.io/BlazorFailsToDeserializeTwoByteArraysAtOnce/
If you try out the demo you see that we get the following exception:
JSException: An exception occurred executing JS interop: JSON serialization is attempting to deserialize an unexpected byte array.. See InnerException for more details.
This is thrown from here: ByteArrayJsonConverter.cs#L33
ByteArraysToBeRevived
becomes empty when another JSInterop invocation has started before the current one finishes deserializing the response as can be seen here: JSRuntime.cs#L200So the core of the problem is that all calls that return a byte array use the same
ArrayBuilder<byte[]> ByteArraysToBeRevived
instance.Expected Behavior
The expected behavior is that we can do multiple JSInterop calls that return byte arrays at once.
This can be fixed by changing
ByteArraysToBeRevived
to be a concurrent dictionary from a long id to a byte array and then not resetting the id that we use to identify each byte array argument in a single invocation which is callednextByteArrayIndex
.This would mean that we no longer use
ArrayBuilder<byte[]>
, which was smart as Blazor would then automatically throw away any references to byte arrays that didn't end up being deserialized. To get around this we would need to ensure that we also "release" or "return" those arrays that we didn't end up deserializing.I would love to supply and collaborate on a PR for fixing this.
Unrelated:
There currently is an unrelated bug that we don't clear
ByteArraysToBeRevived
when a JSInterop task is canceled. The problem is negated by the JSInterop code pessimistically clearing it anyway when making a new call that returns a byte array (or more). Which is probably why that has not been reported previously.Steps To Reproduce
I have a minimal sample of this bug in this repo: https://github.com/KristofferStrube/BlazorFailsToDeserializeTwoByteArraysAtOnce
Which can be demoed live here: https://kristofferstrube.github.io/BlazorFailsToDeserializeTwoByteArraysAtOnce/
Exceptions (if any)
JSException: An exception occurred executing JS interop: JSON serialization is attempting to deserialize an unexpected byte array.. See InnerException for more details.
.NET Version
9.0.101
Anything else?
ASP.NET Core version
9.0.0
IDE: VSCode or Visual Studio
dotnet -info:
The text was updated successfully, but these errors were encountered: