.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 ...
随机推荐
- 人人都是 DBA(XI)I/O 信息收集脚本汇编
什么?有个 SQL 执行了 8 秒! 哪里出了问题?臣妾不知道啊,得找 DBA 啊. DBA 人呢?离职了!!擦!!! 程序员在无处寻求帮助时,就得想办法自救,努力让自己变成 "伪 DBA& ...
- 解决你的开发烦恼——Aoite 开源前奏
Aoite(Any one item!) 一个适于任何 .Net Framework 4.0+ 项目的快速开发整体解决方案,敬请关注 Aoite GitHub. 介绍 本项目从2009年孵化(V-&g ...
- angularjs移除不必要的$watch
在我们的web page,特别是移动设备上,太多的angular $watch将可能导致性能问题.这篇文章将解释如何去移除额外的$watch提高你的应用程序性能. $watch如果不再使用,我们最好将 ...
- 一天一小段js代码(no.3)
//遍历属性,返回名值对 function outputAttributes(element){ var pairs = new Array(), attrName, attrValue, i, le ...
- [翻译].NET随机数
原文链接:http://csharpindepth.com/Articles/Chapter12/Random.aspx 随机数 当你在Stack Overflow上看到看到某个问题标题当中有“随 ...
- HTTP学习笔记(五)
目前,市场上流行有很多web服务器软件,每种服务器都有自己的特点.我们在开发的过程中,经常要和它们打交道,所以了解它们的工作原理也是很重要的. 几款比较流行的服务器 它们会做些什么? 第三篇中有这样的 ...
- 三天学会HTML5——SVG和Canvas的使用
在第一天学习了HTML5的一些非常重要的基本知识,今天将进行更深层学习 首先来回顾第一天学习的内容,第一天学习了新标签,新控件,验证功能,应用缓存等内容. 第2天将学习如何使用Canvas 和使用SV ...
- Nodejs·网络服务
本章是从NodeJS拥有的模块角度,讲述了网络服务中的应用: net ----- > TCP dgram --> UDP http -----> HTTP https ----> ...
- Android 使用Font Awesome 显示文字图标
Android 使用Font Awesome 显示文字图标 简单几步就可以完成 简单的效果图: 1. 创建 assets 文件夹 在Android Studio 上的创建步骤为: 在 src/main ...
- Atitit.编译原理与概论
Atitit.编译原理与概论 编译原理 词法分析 Ast构建,语法分析 语意分析 6 数据结构 1. ▪ 记号 2. ▪ 语法树 3. ▪ 符号表 4. ▪ 常数表 5. ▪ 中间代码 1. ▪ 临 ...