首页 > 代码库 > .Net Task<T>的一种比较神奇的卡死情况(Wait/Result卡死, await能得到结果)
.Net Task<T>的一种比较神奇的卡死情况(Wait/Result卡死, await能得到结果)
出现的环境.Net4.0 + WebApi1(4.0.30506.0) + Microsoft.Bcl.Async.1.0.168
自己死活看不出原因, 分享出来给大家看看,希望有人能找到问题的关键
出现错误的是下面这两个模块
下面的CorsMessageHandler,抄的http://www.cnblogs.com/artech/p/cors-4-asp-net-web-api-04.html, 做了部分修改
1 public class CorsMessageHandler : DelegatingHandler 2 { 3 private static readonly CorsAttribute DEFAULT_CORS = new CorsAttribute("*");//默认支持所有 4 5 protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 6 { 7 cancellationToken.ThrowIfCancellationRequested(); 8 try 9 { 10 //得到描述目标Action的HttpActionDescriptor 11 HttpMethod originalMethod = request.Method; 12 bool isPreflightRequest = request.IsPreflightRequest(); 13 if (isPreflightRequest) 14 { 15 string method = request.Headers.GetValues("Access-Control-Request-Method").First(); 16 request.Method = new HttpMethod(method); 17 } 18 HttpConfiguration configuration = request.GetConfiguration(); 19 HttpControllerDescriptor controllerDescriptor = configuration.Services.GetHttpControllerSelector().SelectController(request); 20 HttpControllerContext controllerContext = new HttpControllerContext(request.GetConfiguration(), request.GetRouteData(), request) 21 { 22 ControllerDescriptor = controllerDescriptor 23 }; 24 //避免权限错误 25 //HttpActionDescriptor actionDescriptor = configuration.Services.GetActionSelector().SelectAction(controllerContext); 26 27 //根据HttpActionDescriptor得到应用的CorsAttribute特性 28 CorsAttribute corsAttribute = null; 29 //corsAttribute = actionDescriptor.GetCustomAttributes<CorsAttribute>().FirstOrDefault(); 30 corsAttribute = corsAttribute?? controllerDescriptor.GetCustomAttributes<CorsAttribute>().FirstOrDefault(); 31 if (null == corsAttribute) 32 { 33 corsAttribute = DEFAULT_CORS; 34 //return base.SendAsync(request, cancellationToken); 35 } 36 37 //利用CorsAttribute实施授权并生成响应报头 38 IDictionary<string, string> headers; 39 request.Method = originalMethod; 40 bool authorized = corsAttribute.TryEvaluate(request, out headers); 41 HttpResponseMessage response; 42 if (isPreflightRequest) 43 { 44 if (authorized) 45 { 46 response = new HttpResponseMessage(HttpStatusCode.OK); 47 } 48 else 49 { 50 response = request.CreateErrorResponse(HttpStatusCode.BadRequest, corsAttribute.ErrorMessage); 51 } 52 } 53 else 54 { 55 var tmp = base.SendAsync(request, cancellationToken); 56 tmp.Wait(); 57 response = tmp.Result; 58 } 59 60 if (headers != null) 61 { 62 foreach (var item in headers) 63 { 64 response.Headers.Add(item.Key, item.Value); 65 } 66 } 67 return response; 68 } 69 catch 70 { 71 } 72 //catch -> fallback 73 return await base.SendAsync(request, cancellationToken); 74 } 75 } 76 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] 77 public class CorsAttribute : Attribute 78 { 79 public Uri[] AllowOrigins { get; private set; } 80 public string ErrorMessage { get; private set; } 81 82 public CorsAttribute(params string[] allowOrigins) 83 { 84 var tmp = (allowOrigins ?? new string[0]); 85 if (tmp.Length == 1 && "*" == tmp[0]) 86 { 87 this.AllowOrigins = null; 88 } 89 else 90 { 91 this.AllowOrigins = tmp.Select(origin => new Uri(origin)).ToArray(); 92 } 93 } 94 95 public bool TryEvaluate(HttpRequestMessage request, out IDictionary<string, string> headers) 96 { 97 headers = null; 98 99 //bugfix: GetValues在找不到时会报错100 IEnumerable<string> origins;101 if (request.Headers.TryGetValues("Origin", out origins))102 {103 string origin = origins.FirstOrDefault();104 if (!String.IsNullOrEmpty(origin))105 {106 Uri originUri = new Uri(origin);107 if (this.AllowOrigins == null || this.AllowOrigins.Contains(originUri))//支持"*"108 {109 headers = this.GenerateResponseHeaders(request);110 return true;111 }112 }113 }114 this.ErrorMessage = "Cross-origin request denied";115 return false;116 }117 118 private IDictionary<string, string> GenerateResponseHeaders(HttpRequestMessage request)119 {120 //设置响应报头"Access-Control-Allow-Methods"121 string origin = request.Headers.GetValues("Origin").First();122 Dictionary<string, string> headers = new Dictionary<string, string>();123 headers.Add("Access-Control-Allow-Origin", origin);124 if (request.IsPreflightRequest())125 {126 //设置响应报头"Access-Control-Request-Headers"127 //和"Access-Control-Allow-Headers"128 string requestHeaders = request.Headers.GetValues("Access-Control-Request-Headers").FirstOrDefault();129 if (!string.IsNullOrEmpty(requestHeaders))130 {131 headers.Add("Access-Control-Allow-Headers", requestHeaders);132 }133 //string requestMethods = request.Headers.GetValues("Access-Control-Request-Method").FirstOrDefault();134 //if (!string.IsNullOrEmpty(requestHeaders))135 //{136 // headers.Add("Access-Control-Allow-Methods", requestMethods + ", OPTIONS");137 //}138 //else139 //{140 headers.Add("Access-Control-Allow-Methods", "*");141 //}142 }143 headers.Add("Access-Control-Allow-Credentials", "true");//true, 允许跨域传cookie, 要在POST的返回值中也存在144 return headers;145 }146 }
一个简单的异常过滤器
1 public class JsonExceptionFilter : FilterAttribute, IExceptionFilter//, IActionFilter 2 { 3 4 public Task ExecuteExceptionFilterAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken) 5 { 6 return Task.Factory.StartNew((obj) => 7 { 8 CancellationToken ct = (CancellationToken)obj; 9 if (actionExecutedContext.Exception != null)10 {11 var res = new ResultModel<String>(false, actionExecutedContext.Exception.GetType().ToString());12 var resText = JsonConvert.SerializeObject(res);13 if (actionExecutedContext.Response == null)14 {15 actionExecutedContext.Response = new HttpResponseMessage();16 }17 actionExecutedContext.Response.Content = new StringContent("{\"State\":-255}", Encoding.UTF8, "application/json");18 }19 }, cancellationToken, cancellationToken);20 }21 }
现在存在的问题是如果Action内部有异常被过滤器捕获, CorsMessageHandler就卡死在
var tmp = base.SendAsync(request, cancellationToken);response = tmp.Result;//卡死在这里, 用tmp.Wait();也是一样卡死
调试看task的State是WaitingForActivation, 但是用Wait/Result无限期卡死无法得到结果, 但是用await(Microsoft.Bcl.Async引入)就不存在问题, 能正常执行出结果
.Net Task<T>的一种比较神奇的卡死情况(Wait/Result卡死, await能得到结果)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。