asynchronous - Why is my call to Azure killing HttpContext.Current -
i have mvc application in have controller receives data user , uploads file azure blob storage. application using unity ioc handle dependency injection.
during workflow have isolated following code demonstrating problem
public class mvccontroller : controller { private idependencyresolver _dependencyresolver; public mvccontroller() : this(dependencyresolver.current) { } public mvccontroller(idependencyresolver dependencyresolver) { this._dependencyresolver = dependencyresolver; } public getservice<t>() { t resolved = _dependencyresolver.getservice<t>() if (resolved == null) throw new exception(string.format("dependency resolver not contain service of type {0}", typeof(t).name)); return resolved; } } public class mycontroller : mvccontroller { [noasynctimeout] public async task<actionresult> savefileasync(/* bunch of arguments */) { /* bunch of code */ //this line gets concrete instance httpcontext.current successfully... imyobject o = getservice<imyobject>(); await savefiletoazure(/* bunch of parameters */); . . /* sometime later */ method2(/* bunch of parameters */); } private method2(/* bunch of parameters */) { //this line fails because httpcontext.current null imyobject o = getservice<imyobject>(); /* bunch of other code */ } private async task savefiletoazure(/* bunch of parameters */) { //grab blob container store file data... cloudblobcontainer blobcontainer = getblobcontainer(); icloudblob blob = blobcontainer.getblockblobreference(somepath); stream datastream = getdata(); system.threading.cancellationtoken canceltoken = getcancellationtoken(); //all calls dependencyresolver.getservice<t>() after line of code fail... response = await blob.uploadstreamasync(datastream, canceltoken); /* bunch of other code */ } }
unity has registration object:
container.registertype<imyobject, myobject>(new httplifetimemanager());
my lifetime manager defined follows:
public sealed class httprequestlifetimemanager : lifetimemanager { public guid key { get; private set; } public httprequestlifetimemanager() { this.key = guid.newguid(); } public override object getvalue() { return httpcontext.current.items[(object)this.key]; } public override void setvalue(object newvalue) { httpcontext.current.items[(object)this.key] = newvalue; } public override void removevalue() { httpcontext.current.items.remove((object)this.key); } }
nothing complicated.
stepping httprequestlifetimemanager on failing getservice() calls shows after uploadstreamasync() call httpcontext.current null...
has else come across problem? if so, bug? expected behaviour? doing out of ordinary? should resolve it?
i can hack around storing reference httpcontext.current prior offending call , restoring after, doesn't seem right approach.
any ideas?
to echo @joachim - http context may not available async thread. compare current thread id can see httpcontext available, thread id can see isn't - i'm assuming see 2 different threads. if assumption correct may sign main thread (the 1 httpcontext) not have "synchronizationcontext". (you can see http://blogs.msdn.com/b/pfxteam/archive/2012/01/20/10259049.aspx more details of how works) if so, may mean code after await statement not running on same thread code prior await statement! perspective, 1 moment have http context , next don't because execution has been switched thread! should @ implementing / setting synchronizationcontext on main thread if that's case , control returned original thread http context , should fix problem, or alternatively retrieve object http context on original thread , find way pass parameter async method/s don't need access http context state.
Comments
Post a Comment