ExecutionContext是否始终流入Task.Run/Parallel.ForEach?ASP.NET请求对象疑问
ASP.NET中嵌套Task.Run/Parallel.ForEach时Request对象的访问问题
我在ASP.NET应用的控制器中大量嵌套使用Task.Run和Parallel.ForEach,层级有时达到2-3层,代码结构如下:
// 此代码位于控制器中(即Request对象处于作用域内) Task.Run(() => { Parallel.ForEach(things, t => { Task.Run(() => { Parallel.ForEach(otherThings, t => { // 等等..
我清楚这种写法并不规范,但我的疑问是:Request对象是否应该能在整个嵌套层级中被访问到?
我查阅资料了解到,ExecutionContext会自动流转到这些异步/并行代码中(除非显式阻止),第一个Task.Run应该会获取和外部代码相同的ExecutionContext,并传递给后续的Parallel.ForEach等,理论上嵌套最深处的代码应该能访问到原调用代码的相同数据。
但实际场景中,我在某些层级遇到了奇怪的空引用错误:Task.Run内部的对象为空,而外部代码中该对象不为空,且错误只出现在特定代码里,我找不到差异点。我是不是误解了ExecutionContext流转的某些细节?
更新:问题根源确认
根据测试验证,问题出在未使用async/await等待任务完成,导致请求已经结束、Request对象被销毁后,后台任务才开始执行,此时自然无法访问到Request相关对象。
可正常运行的测试代码(无限循环)
[Route("test")] public async Task<string> Test() { await Task.Run(() => { var counter = 0; while (true) { counter++; ServiceLocator.Current.GetInstance<IHttpContextAccessor>().HttpContext.Items.Add(counter.ToString(), "foo"); Debug.WriteLine(counter); } }); return "OK"; }
无法运行的测试代码(抛出空引用异常)
[Route("test")] public string Test() { Task.Run(() => { var counter = 0; while (true) { counter++; ServiceLocator.Current.GetInstance<IHttpContextAccessor>().HttpContext.Items.Add(counter.ToString(), "foo"); Debug.WriteLine(counter); } }); return "OK"; }
内容的提问来源于stack exchange,提问作者Deane
相关产品推荐
相关产品推荐

