Skip to content

Commit

Permalink
Improve DotNetStreamReference disposal remarks (#33036)
Browse files Browse the repository at this point in the history
  • Loading branch information
guardrex authored Jul 10, 2024
1 parent 67b5308 commit 4a65b62
Showing 1 changed file with 14 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1213,14 +1213,14 @@ For information on using a byte array when calling .NET from JavaScript, see <xr

## Stream from .NET to JavaScript

Blazor supports streaming data directly from .NET to JavaScript. Streams are created using a <xref:Microsoft.JSInterop.DotNetStreamReference>.
Blazor supports streaming data directly from .NET to JavaScript (JS). Streams are created using a <xref:Microsoft.JSInterop.DotNetStreamReference>.

<xref:Microsoft.JSInterop.DotNetStreamReference> represents a .NET stream and uses the following parameters:

* `stream`: The stream sent to JavaScript.
* `stream`: The stream sent to JS.
* `leaveOpen`: Determines if the stream is left open after transmission. If a value isn't provided, `leaveOpen` defaults to `false`.

In JavaScript, use an array buffer or a readable stream to receive the data:
In JS, use an array buffer or a readable stream to receive the data:

* Using an [`ArrayBuffer`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer):

Expand All @@ -1241,15 +1241,24 @@ In JavaScript, use an array buffer or a readable stream to receive the data:
In C# code:

```csharp
using var streamRef = new DotNetStreamReference(stream: {STREAM}, leaveOpen: false);
var streamRef = new DotNetStreamReference(stream: {STREAM}, leaveOpen: false);
await JS.InvokeVoidAsync("streamToJavaScript", streamRef);
```

In the preceding example:

* The `{STREAM}` placeholder represents the <xref:System.IO.Stream> sent to JavaScript.
* The `{STREAM}` placeholder represents the <xref:System.IO.Stream> sent to JS.
* `JS` is an injected <xref:Microsoft.JSInterop.IJSRuntime> instance.

Disposing a <xref:Microsoft.JSInterop.DotNetStreamReference> instance is usually unnecessary. When `leaveOpen` is set to its default value of `false`, the underlying <xref:System.IO.Stream> is automatically disposed after transmission to JS.

If `leaveOpen` is `true`, then disposing a <xref:Microsoft.JSInterop.DotNetStreamReference> doesn't dispose its underlying <xref:System.IO.Stream>. The app's code determines when to dispose the underlying <xref:System.IO.Stream>. When deciding how to dispose the underlying <xref:System.IO.Stream>, consider the following:

* Disposing a <xref:System.IO.Stream> while it's being transmitted to JS is considered an application error and may cause an unhandled exception to occur.
* <xref:System.IO.Stream> transmission begins as soon as the <xref:Microsoft.JSInterop.DotNetStreamReference> is passed as an argument to a JS interop call, regardless of whether the stream is actually used in JS logic.
Given these characteristics, we recommend disposing the underlying <xref:System.IO.Stream> only after it's fully consumed by JS (the promise returned by `arrayBuffer` or `stream` resolves). It follows that a <xref:Microsoft.JSInterop.DotNetStreamReference> should only be passed to JS if it's unconditionally going to be consumed by JS logic.
<xref:blazor/js-interop/call-dotnet-from-javascript#stream-from-javascript-to-net> covers the reverse operation, streaming from JavaScript to .NET.
<xref:blazor/file-downloads> covers how to download a file in Blazor.
Expand Down

0 comments on commit 4a65b62

Please sign in to comment.