托管式Blazor WebAssembly与SignalR连接问题求助
Blazor WASM PWA + SignalR .NET7 页面提前返回导致WebSocket错误及性能问题
背景
我正在Kubernetes集群中开发包含多种客户端(MVC ASP.NET Web应用、托管式Blazor WebAssembly等)的微服务项目,近期将所有应用升级至.NET 7,不确定是否因此引发问题。
症状
在托管式Blazor WebAssembly(PWA)中,使用SignalR Hub实现Blazor.Client与Blazor.Server间的通信。当调用页面后,在页面完全加载前立即返回,会出现WebSocket错误,同时应用运行极慢。
错误信息
- 组件渲染未处理异常:Cannot access a disposed object.(无法访问已释放的对象)
对象名称: 'HubConnection'。
System.ObjectDisposedException....in HubConnection.SendCoreAsync... - 组件渲染未处理异常:连接未激活时无法调用'SendCoreAsync'方法。
System.InvalidOperationException....in ReconnectingConnectionState.WaitForActiveConnectionAsync...
已尝试的解决方法
因未找到根本原因,尝试捕获上述异常(扩展方法CallAsync):
if ( hubConnection is not null ) { try { await hubConnection.SendAsync( methodName, arg1, arg2, cancellationToken ); } catch ( ObjectDisposedException ) { } catch ( InvalidOperationException ) { } }
但仍收到错误提示:The operation was canceled(操作已取消)。
相关代码
1. 客户端创建Hub连接的方法
var hubConnection = new HubConnectionBuilder() .WithUrl( Navigator.ToAbsoluteUri( hubPath ), options => { options.AccessTokenProvider = () => Task.FromResult( ((AuthStateProvider)AuthStateProv).Token ); // 后续添加的测试代码 options.Transports = Microsoft.AspNetCore.Http.Connections.HttpTransportType.WebSockets; options.SkipNegotiation = true; }) .WithAutomaticReconnect() .Build();
2. 客户端使用Hub连接
// 调用上述方法传入hubPath hubConnection = CreateHubConnection( "/testhub" ); hubConnection.On<MyDataModel>( "ReceiveData", ( result ) => HandleData( result ) ); await hubConnection.StartAsync(); // 调用上述CallAsync方法 await CallAsync( hubConnection, "RequestData" );
3. Razor组件中释放HubConnection
public override async ValueTask DisposeAsync() { if ( hubConnection is not null ) { try { await hubConnection.StopAsync(); } finally { await hubConnection.DisposeAsync(); } } }
4. 服务端Hub代码
public class TestHub : BaseHub { public async Task RequestData() { // 从微服务API获取数据 var result = await _getQuery.Get(); await Clients.Caller.SendAsync( "ReceiveData", result ); } }
5. Blazor.Server启动配置(Program.cs)
builder.Services.AddSignalR( options => { options.ClientTimeoutInterval = TimeSpan.FromSeconds( 60 ); options.HandshakeTimeout = TimeSpan.FromSeconds( 30 ); options.MaximumParallelInvocationsPerClient = 3; options.EnableDetailedErrors = true; } ); builder.Services.AddResponseCompression( opts => { opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat( new[] { "application/octet-stream" } ); } ); var app = builder.Build(); app.UseResponseCompression(); app.MapHub<TestHub>( "/testhub" );
浏览器提示
警告:Web浏览器不支持关闭WebSocket的输出端。CloseOutputAsync已关闭套接字并丢弃所有传入消息。
内容的提问来源于stack exchange,提问作者ibram
相关产品推荐
相关产品推荐

