@@ -592,6 +592,18 @@ await bandwidthLimitManager.WaitForBandwidthAsync(
592592 {
593593 await forwardTask ;
594594 }
595+ else
596+ {
597+ // 无论是否串行,都处理 Task 异常(关键)
598+ forwardTask = forwardTask . ContinueWith ( t =>
599+ {
600+ if ( t . IsFaulted )
601+ {
602+ // 记录异常日志,避免未观察到的异常
603+ logger . LogInformation ( t . Exception , t . Exception . Message , Encoding . UTF8 . GetString ( wsReceiveReader . GetBuffer ( ) ) ) ;
604+ }
605+ } , TaskContinuationOptions . OnlyOnFaulted ) ;
606+ }
595607
596608 // 执行管道 AfterForwardingData
597609 _ = await InvokePipeline ( RequestPipelineStage . AfterForwardingData , PipelineContext . CreateForward ( context , webSocket , result , wsReceiveReader . GetBuffer ( ) , requestScheme , requestBody , webSocketOption ) ) ;
@@ -839,7 +851,7 @@ public static async Task<MvcResponseScheme> MvcDistributeAsync(WebSocketRouteOpt
839851 {
840852 long requestTime = DateTime . Now . Ticks ;
841853 string requestPath = request . Target . ToLower ( ) ;
842-
854+ IServiceScope serviceScope = null ;
843855 try
844856 {
845857 // 从键值对中获取对应的执行函数
@@ -849,20 +861,20 @@ public static async Task<MvcResponseScheme> MvcDistributeAsync(WebSocketRouteOpt
849861 {
850862 goto NotFound ;
851863 }
852- Type clss = webSocketOptions . WatchAssemblyContext . WatchEndPoint . FirstOrDefault ( x => x . MethodPath == requestPath ) ? . Class ;
853- if ( clss == null )
864+ Type targetClass = webSocketOptions . WatchAssemblyContext . WatchEndPoint . FirstOrDefault ( x => x . MethodPath == requestPath ) ? . Class ;
865+ if ( targetClass == null )
854866 {
855867 //找不到访问目标
856868 goto NotFound ;
857869 }
858870
859871 #region 注入Socket的HttpContext和WebSocket客户端
860- webSocketOptions . WatchAssemblyContext . MaxConstructorParameters . TryGetValue ( clss , out ConstructorParameter constructorParameter ) ;
872+ webSocketOptions . WatchAssemblyContext . MaxConstructorParameters . TryGetValue ( targetClass , out ConstructorParameter constructorParameter ) ;
861873
862874 object [ ] instanceParmas = new object [ constructorParameter . ParameterInfos . Length ] ;
863875 // 从Scope DI容器提取目标类构造函数所需的对象
864876 var serviceScopeFactory = WebSocketRouteOption . ApplicationServices . GetService < IServiceScopeFactory > ( ) ;
865- var serviceScope = serviceScopeFactory . CreateScope ( ) ;
877+ serviceScope = serviceScopeFactory . CreateScope ( ) ;
866878 var scopeIocProvider = serviceScope . ServiceProvider ;
867879 for ( int i = 0 ; i < constructorParameter . ParameterInfos . Length ; i ++ )
868880 {
@@ -885,11 +897,11 @@ public static async Task<MvcResponseScheme> MvcDistributeAsync(WebSocketRouteOpt
885897 }
886898 }
887899
888- object inst = Activator . CreateInstance ( clss , instanceParmas ) ;
900+ object inst = Activator . CreateInstance ( targetClass , instanceParmas ) ;
889901
890902 // 使用注入器工厂注入 HttpContext 和 WebSocket(支持源代码生成和反射两种方式)
891903 var injectorFactory = webSocketOptions . InjectorFactory ?? new EndpointInjectorFactory ( webSocketOptions ) ;
892- var injector = injectorFactory . GetOrCreateInjector ( clss ) ;
904+ var injector = injectorFactory . GetOrCreateInjector ( targetClass ) ;
893905 injector . Inject ( inst , context , webSocket ) ;
894906 #endregion
895907
@@ -1064,51 +1076,55 @@ public static async Task<MvcResponseScheme> MvcDistributeAsync(WebSocketRouteOpt
10641076 // Async api support
10651077 if ( invokeResult is Task task )
10661078 {
1067- // 检查是否是 Task<T> 类型
10681079 var taskType = task . GetType ( ) ;
1069- if ( taskType . IsGenericType && taskType . GetGenericTypeDefinition ( ) == typeof ( Task < > ) )
1070- {
1071- // 这是 Task<T>,需要获取返回值
1072- // 先 await 任务完成,避免同步阻塞
1073- await task . ConfigureAwait ( false ) ;
1080+ bool isGenericTask = taskType . IsGenericType && taskType . GetGenericTypeDefinition ( ) == typeof ( Task < > ) ;
10741081
1075- // 检查任务是否有异常
1076- if ( task . IsFaulted && task . Exception != null )
1077- {
1078- // 抛出内部异常(AggregateException 的第一个内部异常)
1079- var innerException = task . Exception . InnerException ?? task . Exception ;
1080- throw innerException ;
1081- }
1082+ // 预先准备好反射所需的 PropertyInfo(如果是 Task<T>)
1083+ PropertyInfo resultProperty = null ;
1084+ if ( isGenericTask ) resultProperty = taskType . GetProperty ( "Result" ) ;
10821085
1083- // 使用反射获取 Result 属性值(此时任务已完成,不会阻塞)
1084- var resultProperty = taskType . GetProperty ( "Result" ) ;
1085- if ( resultProperty != null )
1086+ try
1087+ {
1088+ // 等待任务完成(异步操作,不阻塞线程)
1089+ await task . ConfigureAwait ( false ) ;
1090+ }
1091+ catch ( Exception ex )
1092+ {
1093+ // await 会抛出 AggregateException,提取内部异常
1094+ if ( ex is AggregateException aggEx && aggEx . InnerException != null )
10861095 {
1087- invokeResult = resultProperty . GetValue ( task ) ;
1096+ ex = aggEx . InnerException ;
10881097 }
1098+ mvcResponse = await webSocketOptions . OnException ( ex , request , mvcResponse , context , webSocketOptions , context . Request . Path , logger ) . ConfigureAwait ( false ) ;
10891099 }
1090- else
1100+
1101+ // 检查任务状态(await 后任务已完成,但需要检查是否有异常或取消)
1102+ if ( task . IsFaulted && task . Exception != null )
10911103 {
1092- // 这是 Task(无返回值),直接 await
1093- await task . ConfigureAwait ( false ) ;
1104+ // 抛出内部异常(AggregateException 的第一个内部异常)
1105+ var innerException = task . Exception . InnerException ?? task . Exception ;
1106+ mvcResponse = await webSocketOptions . OnException ( innerException , request , mvcResponse , context , webSocketOptions , context . Request . Path , logger ) . ConfigureAwait ( false ) ;
1107+ }
10941108
1095- // 检查任务是否有异常
1096- if ( task . IsFaulted && task . Exception != null )
1097- {
1098- // 抛出内部异常(AggregateException 的第一个内部异常)
1099- var innerException = task . Exception . InnerException ?? task . Exception ;
1100- throw innerException ;
1101- }
1109+ if ( task . IsCanceled )
1110+ {
1111+ mvcResponse = await webSocketOptions . OnException ( new TaskCanceledException ( task ) , request , mvcResponse , context , webSocketOptions , context . Request . Path , logger ) . ConfigureAwait ( false ) ;
1112+ }
11021113
1114+ // 检查是否是 Task<T> 类型,需要获取返回值
1115+ if ( isGenericTask && resultProperty != null )
1116+ {
1117+ // 使用预先准备好的 PropertyInfo 获取结果(此时任务已完成,不会阻塞)
1118+ invokeResult = resultProperty . GetValue ( task ) ;
1119+ }
1120+ else
1121+ {
11031122 invokeResult = null ;
11041123 }
11051124 }
11061125
11071126 #endregion
11081127
1109- // Dispose ioc scope
1110- serviceScope ? . Dispose ( ) ;
1111- serviceScope = null ;
11121128
11131129 mvcResponse . Id = request . Id ;
11141130 mvcResponse . Target = request . Target ;
@@ -1127,11 +1143,14 @@ public static async Task<MvcResponseScheme> MvcDistributeAsync(WebSocketRouteOpt
11271143
11281144 MvcResponseScheme customResp = await webSocketOptions . OnException ( ex , request , resp , context , webSocketOptions , context . Request . Path , logger ) . ConfigureAwait ( false ) ;
11291145
1130- //if (!webSocketOptions.IsDevelopment)
1131- // resp.Msg = null;
1132-
11331146 return customResp ;
11341147 }
1148+ finally
1149+ {
1150+ // Dispose ioc scope
1151+ serviceScope ? . Dispose ( ) ;
1152+ serviceScope = null ;
1153+ }
11351154
11361155 NotFound :
11371156 logger . LogInformation ( string . Format ( I18nText . WS_INTERACTIVE_TEXT_TEMPALTE , context . Connection . RemoteIpAddress , context . Connection . RemotePort , context . Connection . Id , I18nText . MvcDistributeAsync_EndPointNotFound + requestPath ) ) ;
0 commit comments