Hi Daniil,
Thanks a lot again, but, believe me, I tried this too.
I stayed up until 5am scratching my head as I knew there was something missing.
I was ready to throw in the towel countless times, but to what end?
So, I took my reflector and began to study the disassembled code, I discovered the interesting things.
The httpContext.Current use the static property HostContext, can be found in System.Runtime.Remoting.Messaging
public static object HostContext
{
get
{
object hostContext = Thread.CurrentThread.GetIllogicalCallContext().HostContext;
if (hostContext == null)
{
hostContext = GetLogicalCallContext().HostContext;
}
return hostContext;
}
[SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]
set
{
if (value is ILogicalThreadAffinative)
{
Thread.CurrentThread.GetIllogicalCallContext().HostContext = null;
GetLogicalCallContext().HostContext = value;
}
else
{
GetLogicalCallContext().HostContext = null;
Thread.CurrentThread.GetIllogicalCallContext().HostContext = value;
}
}
}
As we can see the property get use the Thread.CurrentThread.GetIllogicalCallContext().Hos tContext, so, in the LongAction method this will be null because we start a new thread.
I took a look at Session property at HttpCurrent.Context and I discovered it's stored on Items collection using the "AspSession" key.
public HttpSessionState Session
{
get
{
if (this._sessionStateModule != null)
{
lock (this)
{
if (this._sessionStateModule != null)
{
this._sessionStateModule.InitStateStoreItem(true);
this._sessionStateModule = null;
}
}
}
return (HttpSessionState) this.Items["AspSession"];
}
}
Ok! Now I know what I have to do, I have to recreate the current context for the thread.
It's much easier than it looks.
let's the code :)
I create a struct, why struct? because they are value type. I need to guarantee the primary thread will be not redefined when I pass it to state parameter.
/// <summary>
/// used to pass state parameter to method LongAction(object state)
/// </summary>
struct CurrentSessionState
{
public HttpContext Context { get; private set; }
public HttpSessionState Session { get; private set; }
public CurrentSessionState(HttpContext context, HttpSessionState session)
: this()
{
Session = session;
Context = context;
}
}
at LongAction method
private void LongAction(object state)
{
//retrieve CurrentSessionState
CurrentSessionState s = (CurrentSessionState)state;
//force the context to be the same context who that the caller this thread
HttpContext.Current = s.Context;// but the HttpContext.Current.Session still null ... so...
//the Session property is stored on items collection,
//so let we add this item to Items collection
HttpContext.Current.Items["AspSession"] = s.Session;
//done. now we can use httpContext.Current on other threads
for (int i = 0; i < 10; i++)
{
Thread.Sleep(1000);
HttpContext.Current.Session["LongActionProgress"] = i + 1;
}
HttpContext.Current.Session.Remove("LongActionProgress");
}
I recreate the Context
//retrieve CurrentSessionState
CurrentSessionState s = (CurrentSessionState)state;
//force the context to be the same context who that the caller this thread
HttpContext.Current = s.Context;// but the HttpContext.Current.Session still null ... so...
But the session still null. :) But not my "state" parameter because I'm using a struct.
So, let recreate the session
//the Session property is stored on items collection,
//so let we add this item to Items collection
HttpContext.Current.Items["AspSession"] = s.Session;
just it;
Works very well :)
Better than a workaround I have did ... lol
Thanks for your help and patience