.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                 //else
139                 //{
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引入)就不存在问题, 能正常执行出结果

  

时间: 2024-10-13 23:49:38

.Net Task<T>的一种比较神奇的卡死情况(Wait/Result卡死, await能得到结果)的相关文章

java Quartz定时器任务与Spring task定时的几种实现,

java Quartz定时器任务与Spring task定时的几种实现 基于java 的定时任务实现, Quartz 时间详细配置    请查阅   http://www.cnblogs.com/sihuanian/p/5010872.html Quartz 时间简单介绍    请查阅最底部 spring框架来介绍. 一.分类 从实现的技术上来分类,目前主要有三种技术(或者说有三种产品): Java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask

怎么减肥 9种最神奇的快速减肥偏方

这个世界上的减肥方法千奇百怪.层出不穷.但是这些方法不一定都是真正有效的.那么,怎么减肥呢?你知道减肥的最好方法是什么吗?今天小编帮大家总结了九种最神奇的快速减肥偏方,这些减肥方法,或许你没有听过,大家一起来看一下吧. 减肥偏方1:鸡蛋减肥法. 鸡蛋能提高人体血液中的蛋白密度,可以预防血管硬化.鸡蛋减肥法很实用,当你的体重达到标准后,再使摄入热量与热量消耗平衡,就可以使减肥效果持久. 鸡蛋减肥吃法: 就是连续二星期吃白煮蛋.葡萄柚和少量青菜的减肥食谱.一天吃5-9个鸡蛋,分三次吃.每一天的摄取量

C++:四种必须使用初始化列表情况

[c++]必须在类初始化列表中初始化的几种情况 1. 类成员为const类型 2. 类成员为引用类型 复制代码 #include <iostream> using namespace std; class A { public: A(int &v) : i(v), p(v), j(v) {} void print_val() { cout << "hello:" << i << "  " << j

【挑战】计算48种依次泛化的假设情况下,总共有多少种不可再简化的析合范式?

一种可行的算法: 由于属性泛化后,一个泛化的假设可以对应多个具体假设. 把所有假设按三属性泛化,二属性泛化,一属性泛化,具体属性排序(这样可以保证排在后面的假设不会包含前面的任何一个假设,所以省略了一些包含判断),进行循环枚举,按顺序遍历所有假设组合248种可能(当然绝大部分都提前结束了,不会是那么夸张的量级,虽然也不低): 使用栈来实现非递归,如果当前假设还有没被析合式所包含的具体假设,则认为可以入栈,并当前栈大小的长度计数加1,并继续扫描. 如果当前扫描已经到了最后一个假设,或者所有具体假设

在web项目中获取ApplicationContext上下文的3种主要方式及适用情况

最近在做web项目,需要写一些工具方法,涉及到通过Java代码来获取spring中配置的bean,并对该bean进行操作的情形.而最关键的一步就是获取ApplicationContext,过程中纠结和错误了很久,总结一下获取ApplicationContext的三种方式: 方式一:实现ApplicationContextAware接口 对于实现ApplicationContextAware接口的类,spring容器在初始化的时候会扫描他,并把容器的context环境注入给它.如下: 1 publ

一种不能删除文件的情况分析过程

我是root,今有一个文件夹,A 不能删除 rm -rf Arm: cannot remove `A': Read-only file system 1 查看文件夹以及内部文件高级属性,看此文件或者此文件夹内部文件是否有设置了特殊属性 find A -exec lsattr {} \; --------------- ./A/a --------------- ./A/b --------------- ./A/c 文件正常. 2 查看是否被以只读方式挂载. mount /dev/mapper/

两种函数不能重载的情况

首先介绍构成函数重载的条件:函数的参数类型不同,参数个数不同才能构成函数的重载 情况一:  参数完全相同,只有返回值不同 示例 : void print(); int print(); 由于只有返回值不同故无法区分到底调用那个函数,因此不能重载 情况二: 语意不明确 示例: KK(int x , int y = 10){ this->x = 10; this->y = y; } KK(int x){ this->x = 10; this->y = 10; } 完整程序 #inclu

PAT乙级1018.锤子剪刀布 (20)(20 分)

1018 锤子剪刀布 (20)(20 分) 大家应该都会玩“锤子剪刀布”的游戏:两人同时给出手势,胜负规则如图所示: 现给出两人的交锋记录,请统计双方的胜.平.负次数,并且给出双方分别出什么手势的胜算最大. 输入格式: 输入第1行给出正整数N(<=10^5^),即双方交锋的次数.随后N行,每行给出一次交锋的信息,即甲.乙双方同时给出的的手势.C代表“锤子”.J代表“剪刀”.B代表“布”,第1个字母代表甲方,第2个代表乙方,中间有1个空格. 输出格式: 输出第1.2行分别给出甲.乙的胜.平.负次数

JAVA注释的另一种神奇用法

每个JAVA程序员在写程序的时候一定都会用到注释,本篇博客不是讲怎么定义注释,而是说明注释神奇的一种写法. 1 /** 2 * 这是一个测试类 3 */ 4 public class Test { 5 /** 6 * 程序的入口 7 */ 8 public static void main(String[] args) { 9 new Test(); 10 } 11 } 以上是两个普通的多行注释,在IDEA的环境下,选中方法或者类名,按住Ctrl+Q(Eclipse开发环境下直接按住Ctrl然后