Ser*_*e P 21 .net c# asp.net wcf asynchronous
试图访问HttpContext.Current
一个方法调用回来,我可以修改一个Session
变量,但我收到的异常HttpContext.Current
是null
.当_anAgent
对象触发它时,异步触发回调方法.
我的代码的简化版本如下所示:
public partial class Index : System.Web.UI.Page
protected void Page_Load()
{
// aCallback is an Action<string>, triggered when a callback is received
_anAgent = new WorkAgent(...,
aCallback: Callback);
...
HttpContext.Current.Session["str_var"] = _someStrVariable;
}
protected void SendData() // Called on button click
{
...
var some_str_variable = HttpContext.Current.Session["str_var"];
// The agent sends a message to another server and waits for a call back
// which triggers a method, asynchronously.
_anAgent.DispatchMessage(some_str_variable, some_string_event)
}
// This method is triggered by the _webAgent
protected void Callback(string aStr)
{
// ** This culprit throws the null exception **
HttpContext.Current.Session["str_var"] = aStr;
}
[WebMethod(EnableSession = true)]
public static string GetSessionVar()
{
return HttpContext.Current.Session["str_var"]
}
}
Run Code Online (Sandbox Code Playgroud)
不确定是否有必要,但我的WorkAgent
班级是这样的:
public class WorkAgent
{
public Action<string> OnCallbackReceived { get; private set; }
public WorkAgent(...,
Action<string> aCallback = null)
{
...
OnCallbackReceived = aCallback;
}
...
// This method is triggered when a response is received from another server
public BackendReceived(...)
{
...
OnCallbackReceived(some_string);
}
}
Run Code Online (Sandbox Code Playgroud)
代码中发生了什么:
单击按钮调用SendData()
方法,在此内部_webAgent
将消息发送到另一个服务器并等待回复(同时用户仍然可以与此页面交互并参考相同的内容SessionID
).收到后,它会调用BackendReceived()
方法,该方法返回到.aspx.cs页面调用该Callback()
方法.
问:
当WorkAgent
触发该Callback()
方法尝试访问HttpContext.Current
它null
.为什么如果我继续,忽略异常,我仍然可以使用ajax返回的方法获得相同SessionID
和Session
变量GetSessionVar()
.
我应该启用aspNetCompatibilityEnabled设置吗?
我应该创建某种异步模块处理程序吗?
这与集成/经典模式有关吗?
cro*_*sek 10
这是一个基于类的解决方案,适用于MVC5中迄今为止的简单案例(MVC6支持基于DI的上下文).
using System.Threading;
using System.Web;
namespace SomeNamespace.Server.ServerCommon.Utility
{
/// <summary>
/// Preserve HttpContext.Current across async/await calls.
/// Usage: Set it at beginning of request and clear at end of request.
/// </summary>
static public class HttpContextProvider
{
/// <summary>
/// Property to help ensure a non-null HttpContext.Current.
/// Accessing the property will also set the original HttpContext.Current if it was null.
/// </summary>
static public HttpContext Current => HttpContext.Current ?? (HttpContext.Current = __httpContextAsyncLocal?.Value);
/// <summary>
/// MVC5 does not preserve HttpContext across async/await calls. This can be used as a fallback when it is null.
/// It is initialzed/cleared within BeginRequest()/EndRequest()
/// MVC6 may have resolved this issue since constructor DI can pass in an HttpContextAccessor.
/// </summary>
static private AsyncLocal<HttpContext> __httpContextAsyncLocal = new AsyncLocal<HttpContext>();
/// <summary>
/// Make the current HttpContext.Current available across async/await boundaries.
/// </summary>
static public void OnBeginRequest()
{
__httpContextAsyncLocal.Value = HttpContext.Current;
}
/// <summary>
/// Stops referencing the current httpcontext
/// </summary>
static public void OnEndRequest()
{
__httpContextAsyncLocal.Value = null;
}
}
}
Run Code Online (Sandbox Code Playgroud)
要使用它可以从Global.asax.cs挂钩:
public MvcApplication() // constructor
{
PreRequestHandlerExecute += new EventHandler(OnPreRequestHandlerExecute);
EndRequest += new EventHandler(OnEndRequest);
}
protected void OnPreRequestHandlerExecute(object sender, EventArgs e)
{
HttpContextProvider.OnBeginRequest(); // preserves HttpContext.Current for use across async/await boundaries.
}
protected void OnEndRequest(object sender, EventArgs e)
{
HttpContextProvider.OnEndRequest();
}
Run Code Online (Sandbox Code Playgroud)
然后可以使用它来代替HttpContext.Current:
HttpContextProvider.Current
Run Code Online (Sandbox Code Playgroud)
可能存在问题,因为我目前不理解这个相关的答案.请评论.
参考: AsyncLocal (需要.NET 4.6)
当使用线程或async
函数时,HttpContext.Current
不可用。
尝试使用:
HttpContext current;
if(HttpContext != null && HttpContext.Current != null)
{
current = HttpContext.Current;
}
else
{
current = this.CurrentContext;
//**OR** current = threadInstance.CurrentContext;
}
Run Code Online (Sandbox Code Playgroud)
一旦设置了current
正确的实例,代码的其余部分都是独立的,无论是从线程调用还是直接从WebRequest
.
请参阅以下文章,了解 Session 变量为何为 null 的说明以及可能的解决方法
\n\nhttp://adventuresdotnet.blogspot.com/2010/10/httpcontextcurrent-and-threads-with.html
\n\n引自文章;
\n\n\n\n\n当前的
\nHttpContext
实际上位于线程本地存储中,这解释了为什么子线程无法访问它
正如作者提出的一项工作所说
\n\n\n\n在您的子线程中传递对它的引用。在回调方法的 \xe2\x80\x9cstate\xe2\x80\x9d 对象中包含对的引用
\nHttpContext
,然后可以将其存储到HttpContext.Current
该线程上
归档时间: |
|
查看次数: |
25893 次 |
最近记录: |