.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

出现的环境.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, 做了部分修改

.Net Task<T>的一种比较神奇的卡死情况(Wait/Result卡死, await能得到结果)第1张.Net Task<T>的一种比较神奇的卡死情况(Wait/Result卡死, await能得到结果)第2张
1     public classCorsMessageHandler : 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 = newHttpMethod(method);
17 }
18                 HttpConfiguration configuration =request.GetConfiguration();
19                 HttpControllerDescriptor controllerDescriptor =configuration.Services.GetHttpControllerSelector().SelectController(request);
20                 HttpControllerContext controllerContext = newHttpControllerContext(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, outheaders);
41 HttpResponseMessage response;
42                 if(isPreflightRequest)
43 {
44                     if(authorized)
45 {
46                         response = newHttpResponseMessage(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 inheaders)
63 {
64 response.Headers.Add(item.Key, item.Value);
65 }
66 }
67                 returnresponse;
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 classCorsAttribute : 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 => newUri(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", outorigins))
102 {
103                 string origin =origins.FirstOrDefault();
104                 if (!String.IsNullOrEmpty(origin))
105 {
106                     Uri originUri = newUri(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                 //else
139                 //{
140                     headers.Add("Access-Control-Allow-Methods", "*");
141                 //}
142 }
143             headers.Add("Access-Control-Allow-Credentials", "true");//true, 允许跨域传cookie, 要在POST的返回值中也存在
144             returnheaders;
145 }
146     }
View Code

一个简单的异常过滤器

.Net Task&lt;T&gt;的一种比较神奇的卡死情况(Wait/Result卡死, await能得到结果)第3张.Net Task&lt;T&gt;的一种比较神奇的卡死情况(Wait/Result卡死, await能得到结果)第4张
1     public class JsonExceptionFilter : FilterAttribute, IExceptionFilter//, IActionFilter
2 {
3 
4         publicTask 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 = newHttpResponseMessage();
16 }
17                     actionExecutedContext.Response.Content = new StringContent("{"State":-255}", Encoding.UTF8, "application/json");
18 }
19 }, cancellationToken, cancellationToken);
20 }
21     }
View Code

现在存在的问题是如果Action内部有异常被过滤器捕获,CorsMessageHandler就卡死在

vartmp=base.SendAsync(request,cancellationToken);
response=tmp.Result;//卡死在这里, 用tmp.Wait();也是一样卡死

调试看task的State是WaitingForActivation, 但是用Wait/Result无限期卡死无法得到结果, 但是用await(Microsoft.Bcl.Async引入)就不存在问题, 能正常执行出结果

免责声明:文章转载自《.Net Task&amp;lt;T&amp;gt;的一种比较神奇的卡死情况(Wait/Result卡死, await能得到结果)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇三极管的妙用之C118自动刷机[安卓开发]App Widget开发入门指导下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

HTTP metadata数据

信息元位置 信息元名称 信息元ID 信息元描述 1 MetadataVersion 5000 Metadata版本号 当前版本号为1.0 2 MetadataID 1019 MetadataID 3 sourceIPv4Address or sourceIPv6Address 8 or 27 源IP(IPv4或者IPv6)...

java后台解决跨域问题

解决跨域问题的方式有很多,这里主要是添加注解的方式和采用添加拦截器的方法: 方法一、spring boot中只用在Controller类上添加一个“@CrossOrigin“注解就可以实现对当前controller 的跨域 访问了,当然这个标签也可以加到方法上。 @CrossOrigin public classCommonController { }...

十进制,八进制,十六进制,二进制相互转换大全

轉自:http://blog.programfan.com/article.asp?id=11903   ' 用途:将十进制转化为二进制' 输入:Dec(十进制数)' 输入数据类型:Long' 输出:DEC_to_BIN(二进制数)' 输出数据类型:String' 输入的最大数为2147483647,输出最大数为111111111111111111111...

FileUpload控件使用初步

FileUpload控件使用初步: 1.实现文件上传 protected void btnSubmit_click(object sender, EventArgs e) { if (FileUpload1.HasFile == true) { string strErr = ""; //获得上传文件的大小 int filesize = FileUploa...

Shiro权限管理框架(四):深入分析Shiro中的Session管理

其实关于Shiro的一些学习笔记很早就该写了,因为懒癌和拖延症晚期一直没有落实,直到今天公司的一个项目碰到了在集群环境的单点登录频繁掉线的问题,为了解决这个问题,Shiro相关的文档和教程没少翻。最后问题解决了,但我觉得我也是时候来做一波Shiro学习笔记了。 本篇是Shiro系列第四篇,Shiro中的过滤器初始化流程和实现原理。Shiro基于URL的权限...

Java性能优化之String字符串优化

1.字符串对象及其特点 Java中八大基本数据类型没有String类型,因为String类型是Java对char数组的进一步封装。 String类的实现主要由三部分组成:char数组,offset偏移量,String的长度。 String类型有三个基本特点: 不变性 不变性是指String对象一旦生成,则不能再对它进行改变。 不变性的作用在于当一个对象...