Repository: dotnet/aspnetcore
File: src/Components/Server/src/Circuits/CircuitHost.cs (C#)

Code before:

    // We handle errors in DisposeAsync because there's no real value in letting it propagate.
    // We run user code here (CircuitHandlers) and it's reasonable to expect some might throw, however,
    // there isn't anything better to do than log when one of these exceptions happens - because the
    // client is already gone.
    public async ValueTask DisposeAsync()
    {
        Log.DisposeStarted(_logger, CircuitId);

        await Renderer.Dispatcher.InvokeAsync(async () =>
        {
            if (_disposed)
            {
                return;
            }

            // Make sure that no hub or connection can refer to this circuit anymore now that it's shutting down.
            Handle.CircuitHost = null;
            _disposed = true;

            try
            {
                if (this.Client.Connected)
                {
                    await OnConnectionDownAsync(CancellationToken.None);
                }
            }
            catch
            {
                // Individual exceptions logged as part of OnConnectionDownAsync - nothing to do here
                // since we're already shutting down.
            }

            try
            {
                await OnCircuitDownAsync(CancellationToken.None);
            }
            catch
            {
                // Individual exceptions logged as part of OnCircuitDownAsync - nothing to do here
                // since we're already shutting down.
            }

            try
            {
                // Prevent any further JS interop calls
                // Helps with scenarios like https://github.com/dotnet/aspnetcore/issues/32808
                JSRuntime.MarkPermanentlyDisconnected();

                await Renderer.DisposeAsync();
                await _scope.DisposeAsync();

Review comment (suggestion):
I don't think this is the right change to fix the metric issue. It's changing an existing behavior of the system that users might be relying on.

Code after:
    }

    // We handle errors in DisposeAsync because there's no real value in letting it propagate.
    // We run user code here (CircuitHandlers) and it's reasonable to expect some might throw, however,
    // there isn't anything better to do than log when one of these exceptions happens - because the
    // client is already gone.
    public async ValueTask DisposeAsync()
    {
        Log.DisposeStarted(_logger, CircuitId);

        await Renderer.Dispatcher.InvokeAsync(async () =>
        {
            if (_disposed)
            {
                return;
            }

            // Make sure that no hub or connection can refer to this circuit anymore now that it's shutting down.
            Handle.CircuitHost = null;
            _disposed = true;

            try
            {
                await OnConnectionDownAsync(CancellationToken.None);
            }
            catch
            {
                // Individual exceptions logged as part of OnConnectionDownAsync - nothing to do here
                // since we're already shutting down.
            }

            try
            {
                await OnCircuitDownAsync(CancellationToken.None);
            }
            catch
            {
                // Individual exceptions logged as part of OnCircuitDownAsync - nothing to do here
                // since we're already shutting down.
            }

            try
            {
                // Prevent any further JS interop calls
                // Helps with scenarios like https://github.com/dotnet/aspnetcore/issues/32808
                JSRuntime.MarkPermanentlyDisconnected();

                await Renderer.DisposeAsync();
                await _scope.DisposeAsync();

                Log.DisposeSucceeded(_logger, CircuitId);