出现的环境.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能得到结果)的更多相关文章

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

    java Quartz定时器任务与Spring task定时的几种实现 基于java 的定时任务实现, Quartz 时间详细配置    请查阅   http://www.cnblogs.com/si ...

  2. 四大组件之Activity Task任务栈4种启动模式

    1.启动模式 standard,创建一个新的Activity. singleTop,栈顶不是该类型的Activity,创建一个新的Activity.否则,onNewIntent. singleTask ...

  3. Delegate、Thread、Task、ThreadPool几种方式创建异步任务性能对比

    开始预测的结果是 Task>Delegate>ThreadPool>>Thread. (一)测试代码 static async Task<int> AsyncTas ...

  4. async await task.Result 卡死

    在如下代码中: public async Task<string> GetData() { return await DoWork(); } 在UI线程中调用 var data = Get ...

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

    [c++]必须在类初始化列表中初始化的几种情况   1. 类成员为const类型   2. 类成员为引用类型   复制代码 #include <iostream> using namesp ...

  6. vue-router两种模式,到底什么情况下用hash,什么情况下用history模式呢?

    转:https://segmentfault.com/q/1010000010340823/a-1020000010598395 为什么要有 hash 和 history 对于 Vue 这类渐进式前端 ...

  7. JAVA中空指针异常报错的几种可能坑你的情况

    一.局部变量覆盖掉其他变量导致无法使用. 在做Java客户管理的项目的时候,eclipse报出了个空指针异常的错误,但反复检查也并没感觉出错误,调用的数组给它初始化而且赋值了,但是编译器很顽强的报了一 ...

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

    最近在做web项目,需要写一些工具方法,涉及到通过Java代码来获取spring中配置的bean,并对该bean进行操作的情形.而最关键的一步就是获取ApplicationContext,过程中纠结和 ...

  9. 数据库SQL调优的几种方式 EFcore读的情况下使用 AsNoTracking非跟踪查询

    不要用GUID 当主键 没有规律 可以用雪花ID DBA 优化法则 硬件资源是根本,DBA是为了充分利用硬件资源 一般清空下可以不使用外键 可以提高性能 合理使用临时表 临时表分页; 一些查询语句加w ...

随机推荐

  1. 【C语言学习】《C Primer Plus》第2章 C语言的概述

    学习总结 1.#include是C预处理命令之一,#include指向的是头文件,如#include <stdio.h>,这个stdio.h就是程序需要引用的C标准库之一.里面包含了pri ...

  2. Windows Azure Service Bus Notification Hub推送通知

    前言 随着Windows Azure 在中国的正式落地,相信越来越多的人会体验到Windows Azure带来的强大和便利.在上一篇文章中, 我们介绍了如何利用Windows Azure中的Servi ...

  3. WCF Data Service

    WCF Data Service:http://www.cnblogs.com/shanyou/category/240225.html

  4. Android多线程分析之四:MessageQueue的实现

    Android多线程分析之四:MessageQueue的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前面两篇文章<Androi ...

  5. Dynamics CRM 2013 installation

    原创地址:http://www.cnblogs.com/jfzhu/p/3445820.html 转载请注明出处 一 硬件要求 1. CRM Server 下表对硬件的要求是假定Microsoft S ...

  6. Atitit java 二维码识别 图片识别

    Atitit java 二维码识别 图片识别 1.1. 解码11.2. 首先,我们先说一下二维码一共有40个尺寸.官方叫版本Version.11.3. 二维码的样例:21.4. 定位图案21.5. 数 ...

  7. Linux运维之道(大量经典案例、问题分析,运维案头书,红帽推荐)

    Linux运维之道(大量经典案例.问题分析,运维案头书,红帽推荐) 丁明一 编   ISBN 978-7-121-21877-4 2014年1月出版 定价:69.00元 448页 16开 编辑推荐 1 ...

  8. iOS-数据解析XML解析的多种平台介绍

    在iPhone开发中,XML的解析有很多选择,iOS SDK提供了NSXMLParser和libxml2两个类库,另外还有很多第三方类库可选,例如TBXML.TouchXML.KissXML.Tiny ...

  9. java之设计模式

    一.代理模式 a.抽象角色(接口):声明真实对象和代理对象的共同接口 b.代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能替 ...

  10. Liferay7 BPM门户开发之45: 集成Activiti文件上传部署流程BPMN模型

    开发文件上传,部署流程模板. 首先,开发jsp页面,deploy.jsp <%@ include file="/init.jsp" %> <h3>${RET ...