.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 ...
随机推荐
- Guava - EventBus(事件总线)
Guava在guava-libraries中为我们提供了事件总线EventBus库,它是事件发布订阅模式的实现,让我们能在领域驱动设计(DDD)中以事件的弱引用本质对我们的模块和领域边界很好的解耦设计 ...
- Android Fragment add/replace以及backstack
无论Fragment以何种方式加入,都不会影响backstack,backstack由addToBackStack函数决定,只有调用了这个函数,才会将Fragment加入返回栈.这个说法其实不太准确, ...
- SQL—大话函数依赖与范式
说明:数据库中的某些概念真的很让人头疼,概念的东西本来就是很枯燥的,再加上枯燥的学习,那就更加枯燥了.概念这东西,你不理解也能生产东西,经验多了就行,但是为了更深入的学习,你还必须理解.这里,我抛开书 ...
- okhttp教程——起步篇
okhttp教程--起步篇 这篇文章主要总结Android著名网络框架-okhttp的基础使用,后续可能会有关于他的高级使用. okhttp是什么 okhttp是Android端的一个Http客户端, ...
- Springlake-01 介绍&功能&安装
1. 简介与功能 1)Springlake 是一个企业内容平台SECP 2)是一个可配置的系统,80%内容可以配置 3)允许建立和配置垂直解决方案 4)敏捷和占用空间小,可伸缩 5)端到端的安全性与性 ...
- Atitit。木马病毒原理机密与概论以及防御
Atitit.木马病毒原理机密与概论以及防御 1. 定时截屏木马1 1.1. QQ聊天与微信聊天木马1 2. 文档木马1 3. 病毒木马的触发方式2 4. 远程木马2 5. 漏洞木马2 6. 病毒木马 ...
- Maven Myeclipse 搭建项目
一.maven概述 Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具! 简单说Maven 是一个项目管理和构建自动化工具 二.环境搭建 1. ...
- KnockoutJS 3.X API 第五章 高级应用(4) 自定义处理逻辑
在典型的Knockout应用程序中,DOM元素是动态添加和删除的,例如使用模板绑定或通过控制流绑定(if,ifnot,with和foreach). 当创建自定义绑定时,通常需要添加清除逻辑,当Knoc ...
- CSS布局中的问题
1. 高度自适应的问题 1. 一个元素是否可以使用百分比显示,取决于它的父级元素,所以如果需要给此元素设置100%,那么需要先给父元素设置高100%. 2. 一级元素的父元素是body,所以如果我们想 ...
- 将 PAGE_VERIFY 数据库选项设置为 CHECKSUM
此规则检查 PAGE_VERIFY 数据库选项是否已设置为 CHECKSUM.为 PAGE_VERIFY 数据库选项启用 CHECKSUM 后,SQL Server 数据库引擎会在向磁盘中写入页面时计 ...