在使用 await Task.Factory.FromAsync(BeginXxx, EndXxx) 后,HttpContext 为空。

4
我有一个Asp.Net应用程序,使用svcutil生成的代理调用一些WCF服务。 生成的代理在APM模式(BeginXxx,EndXxx)中具有异步方法。
为了利用新的async/await模式,我使用了async targeting pack,并且我的目标平台是.net 4.0(否则我就不必使用async targeting pack)。
我使用Task.Factory.FromAsync将APM模式转换为可等待的任务。
我的代码看起来有点像这样(假设服务方法不带参数并返回int:
int result = await Task<int>.Factory.FromAsync(proxy.BeginXxx, proxy.EndXxx, state: null);
HttpContext.Current.Items["reuslt"] = result;

第二行抛出了一个NullReferenceException
我认为原因是回调(即在await调用之后运行的所有内容)没有原始同步上下文。
其他方法(如Factory.StartNew)有重载,接收可以用于保留上下文的TaskScheduler
FromAsync方法也有重载,它们接收TaskScheduler,但没有将begin方法作为参数的重载。
假设我不想手动将Http上下文作为方法参数传递给此行之后调用的所有方法,那么我该如何使用获取任务调度程序的重载或以其他方式使.Net尊重我的同步上下文?

你确定在调用 FromAsync 前已经正确设置了 SyncContext 吗? - usr
在 FromAsync 调用之前,我可以访问 HttpContext。 - rony l
1个回答

5
我怀疑问题实际上在ASP.NET管道中,而不是在SynchronizationContext中。
Async Targeting Pack支持async/await,但是ASP.NET 4.5中有很多改变使其支持async,而Targeting Pack并不包括该支持。
尝试通过使用RegisterAsyncTask(用于Web Forms)或AsyncManager(用于MVC)来帮助ASP.NET管道。即使这样,在管道中仍然有一些地方无法接受异步代码(在ASP.NET 4.5中仍然是真实的,但至少4.5会检测到并抛出错误)。

所以我尝试使用接收调度程序的重载,但没有成功。看起来你的分析是正确的。我在流程开始时获取了HttpContext.Current(当它还不为null时),并将其传递到流程的其余部分。 - rony l
有关在IIS和.NET 4.5中使用WebAPI的任何提示吗?与@ronyl相同。 - Konstantin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接