.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, 做了部分修改
public class CorsMessageHandler : DelegatingHandler
{
private static readonly CorsAttribute DEFAULT_CORS = new CorsAttribute("*");//默认支持所有 protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
try
{
//得到描述目标Action的HttpActionDescriptor
HttpMethod originalMethod = request.Method;
bool isPreflightRequest = request.IsPreflightRequest();
if (isPreflightRequest)
{
string method = request.Headers.GetValues("Access-Control-Request-Method").First();
request.Method = new HttpMethod(method);
}
HttpConfiguration configuration = request.GetConfiguration();
HttpControllerDescriptor controllerDescriptor = configuration.Services.GetHttpControllerSelector().SelectController(request);
HttpControllerContext controllerContext = new HttpControllerContext(request.GetConfiguration(), request.GetRouteData(), request)
{
ControllerDescriptor = controllerDescriptor
};
//避免权限错误
//HttpActionDescriptor actionDescriptor = configuration.Services.GetActionSelector().SelectAction(controllerContext); //根据HttpActionDescriptor得到应用的CorsAttribute特性
CorsAttribute corsAttribute = null;
//corsAttribute = actionDescriptor.GetCustomAttributes<CorsAttribute>().FirstOrDefault();
corsAttribute = corsAttribute?? controllerDescriptor.GetCustomAttributes<CorsAttribute>().FirstOrDefault();
if (null == corsAttribute)
{
corsAttribute = DEFAULT_CORS;
//return base.SendAsync(request, cancellationToken);
} //利用CorsAttribute实施授权并生成响应报头
IDictionary<string, string> headers;
request.Method = originalMethod;
bool authorized = corsAttribute.TryEvaluate(request, out headers);
HttpResponseMessage response;
if (isPreflightRequest)
{
if (authorized)
{
response = new HttpResponseMessage(HttpStatusCode.OK);
}
else
{
response = request.CreateErrorResponse(HttpStatusCode.BadRequest, corsAttribute.ErrorMessage);
}
}
else
{
var tmp = base.SendAsync(request, cancellationToken);
tmp.Wait();
response = tmp.Result;
} if (headers != null)
{
foreach (var item in headers)
{
response.Headers.Add(item.Key, item.Value);
}
}
return response;
}
catch
{
}
//catch -> fallback
return await base.SendAsync(request, cancellationToken);
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CorsAttribute : Attribute
{
public Uri[] AllowOrigins { get; private set; }
public string ErrorMessage { get; private set; } public CorsAttribute(params string[] allowOrigins)
{
var tmp = (allowOrigins ?? new string[]);
if (tmp.Length == && "*" == tmp[])
{
this.AllowOrigins = null;
}
else
{
this.AllowOrigins = tmp.Select(origin => new Uri(origin)).ToArray();
}
} public bool TryEvaluate(HttpRequestMessage request, out IDictionary<string, string> headers)
{
headers = null; //bugfix: GetValues在找不到时会报错
IEnumerable<string> origins;
if (request.Headers.TryGetValues("Origin", out origins))
{
string origin = origins.FirstOrDefault();
if (!String.IsNullOrEmpty(origin))
{
Uri originUri = new Uri(origin);
if (this.AllowOrigins == null || this.AllowOrigins.Contains(originUri))//支持"*"
{
headers = this.GenerateResponseHeaders(request);
return true;
}
}
}
this.ErrorMessage = "Cross-origin request denied";
return false;
} private IDictionary<string, string> GenerateResponseHeaders(HttpRequestMessage request)
{
//设置响应报头"Access-Control-Allow-Methods"
string origin = request.Headers.GetValues("Origin").First();
Dictionary<string, string> headers = new Dictionary<string, string>();
headers.Add("Access-Control-Allow-Origin", origin);
if (request.IsPreflightRequest())
{
//设置响应报头"Access-Control-Request-Headers"
//和"Access-Control-Allow-Headers"
string requestHeaders = request.Headers.GetValues("Access-Control-Request-Headers").FirstOrDefault();
if (!string.IsNullOrEmpty(requestHeaders))
{
headers.Add("Access-Control-Allow-Headers", requestHeaders);
}
//string requestMethods = request.Headers.GetValues("Access-Control-Request-Method").FirstOrDefault();
//if (!string.IsNullOrEmpty(requestHeaders))
//{
// headers.Add("Access-Control-Allow-Methods", requestMethods + ", OPTIONS");
//}
//else
//{
headers.Add("Access-Control-Allow-Methods", "*");
//}
}
headers.Add("Access-Control-Allow-Credentials", "true");//true, 允许跨域传cookie, 要在POST的返回值中也存在
return headers;
}
}
一个简单的异常过滤器
public class JsonExceptionFilter : FilterAttribute, IExceptionFilter//, IActionFilter
{ public Task ExecuteExceptionFilterAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken)
{
return Task.Factory.StartNew((obj) =>
{
CancellationToken ct = (CancellationToken)obj;
if (actionExecutedContext.Exception != null)
{
var res = new ResultModel<String>(false, actionExecutedContext.Exception.GetType().ToString());
var resText = JsonConvert.SerializeObject(res);
if (actionExecutedContext.Response == null)
{
actionExecutedContext.Response = new HttpResponseMessage();
}
actionExecutedContext.Response.Content = new StringContent("{\"State\":-255}", Encoding.UTF8, "application/json");
}
}, cancellationToken, cancellationToken);
}
}
现在存在的问题是如果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能得到结果)的更多相关文章
- java Quartz定时器任务与Spring task定时的几种实现,
java Quartz定时器任务与Spring task定时的几种实现 基于java 的定时任务实现, Quartz 时间详细配置 请查阅 http://www.cnblogs.com/si ...
- 四大组件之Activity Task任务栈4种启动模式
1.启动模式 standard,创建一个新的Activity. singleTop,栈顶不是该类型的Activity,创建一个新的Activity.否则,onNewIntent. singleTask ...
- Delegate、Thread、Task、ThreadPool几种方式创建异步任务性能对比
开始预测的结果是 Task>Delegate>ThreadPool>>Thread. (一)测试代码 static async Task<int> AsyncTas ...
- async await task.Result 卡死
在如下代码中: public async Task<string> GetData() { return await DoWork(); } 在UI线程中调用 var data = Get ...
- C++:四种必须使用初始化列表情况
[c++]必须在类初始化列表中初始化的几种情况 1. 类成员为const类型 2. 类成员为引用类型 复制代码 #include <iostream> using namesp ...
- vue-router两种模式,到底什么情况下用hash,什么情况下用history模式呢?
转:https://segmentfault.com/q/1010000010340823/a-1020000010598395 为什么要有 hash 和 history 对于 Vue 这类渐进式前端 ...
- JAVA中空指针异常报错的几种可能坑你的情况
一.局部变量覆盖掉其他变量导致无法使用. 在做Java客户管理的项目的时候,eclipse报出了个空指针异常的错误,但反复检查也并没感觉出错误,调用的数组给它初始化而且赋值了,但是编译器很顽强的报了一 ...
- 在web项目中获取ApplicationContext上下文的3种主要方式及适用情况
最近在做web项目,需要写一些工具方法,涉及到通过Java代码来获取spring中配置的bean,并对该bean进行操作的情形.而最关键的一步就是获取ApplicationContext,过程中纠结和 ...
- 数据库SQL调优的几种方式 EFcore读的情况下使用 AsNoTracking非跟踪查询
不要用GUID 当主键 没有规律 可以用雪花ID DBA 优化法则 硬件资源是根本,DBA是为了充分利用硬件资源 一般清空下可以不使用外键 可以提高性能 合理使用临时表 临时表分页; 一些查询语句加w ...
随机推荐
- 【C语言学习】《C Primer Plus》第2章 C语言的概述
学习总结 1.#include是C预处理命令之一,#include指向的是头文件,如#include <stdio.h>,这个stdio.h就是程序需要引用的C标准库之一.里面包含了pri ...
- Windows Azure Service Bus Notification Hub推送通知
前言 随着Windows Azure 在中国的正式落地,相信越来越多的人会体验到Windows Azure带来的强大和便利.在上一篇文章中, 我们介绍了如何利用Windows Azure中的Servi ...
- WCF Data Service
WCF Data Service:http://www.cnblogs.com/shanyou/category/240225.html
- Android多线程分析之四:MessageQueue的实现
Android多线程分析之四:MessageQueue的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前面两篇文章<Androi ...
- Dynamics CRM 2013 installation
原创地址:http://www.cnblogs.com/jfzhu/p/3445820.html 转载请注明出处 一 硬件要求 1. CRM Server 下表对硬件的要求是假定Microsoft S ...
- Atitit java 二维码识别 图片识别
Atitit java 二维码识别 图片识别 1.1. 解码11.2. 首先,我们先说一下二维码一共有40个尺寸.官方叫版本Version.11.3. 二维码的样例:21.4. 定位图案21.5. 数 ...
- Linux运维之道(大量经典案例、问题分析,运维案头书,红帽推荐)
Linux运维之道(大量经典案例.问题分析,运维案头书,红帽推荐) 丁明一 编 ISBN 978-7-121-21877-4 2014年1月出版 定价:69.00元 448页 16开 编辑推荐 1 ...
- iOS-数据解析XML解析的多种平台介绍
在iPhone开发中,XML的解析有很多选择,iOS SDK提供了NSXMLParser和libxml2两个类库,另外还有很多第三方类库可选,例如TBXML.TouchXML.KissXML.Tiny ...
- java之设计模式
一.代理模式 a.抽象角色(接口):声明真实对象和代理对象的共同接口 b.代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能替 ...
- Liferay7 BPM门户开发之45: 集成Activiti文件上传部署流程BPMN模型
开发文件上传,部署流程模板. 首先,开发jsp页面,deploy.jsp <%@ include file="/init.jsp" %> <h3>${RET ...