为什么Task.Run包裹的代码未执行,单独运行内部MakeRequest却正常?
问题核心原因
你碰到的问题本质上是ASP.NET 上下文在线程池线程不可访问,以及缺少任务异常检查两个点共同导致的:
System.Web.HttpContext.Current仅在处理请求的原始线程中有效,你用Task.Run把逻辑丢到线程池线程执行时,HttpContext.Current会直接返回null,第一行获取文件路径的代码就会抛出空引用异常,后续的请求调用、文件写入逻辑自然不会执行。- 你用的
ContinueWith默认不管前置任务是执行成功、抛出异常还是被取消都会触发,所以哪怕前面的逻辑全崩了,还是会输出t2 done,你看不到任何错误提示,自然会以为逻辑跑了但没生效。 - 单独跑
Helper.MakeRequest那一行的时候是在请求的原始线程执行,HttpContext是正常存在的,所以不会出问题。
额外可能的影响点
如果修复上下文问题后还是有概率不生效,是因为ASP.NET 中请求结束后,未注册的后台任务可能会被应用域直接回收终止,不会等到执行完成。
修复方案
- 所有和
HttpContext相关的取值操作,都放到主线程提前执行完成,再把值传到Task.Run的委托里,不要在子线程访问上下文。 - 在
ContinueWith里增加任务状态检查,捕获异常方便排查。 - ASP.NET Framework 场景下如果确实需要跑后台任务,推荐用
HostingEnvironment.QueueBackgroundWorkItem注册任务,避免被提前回收。
修复后参考代码
// 主线程提前取所有上下文、配置值 string baseFilePath = System.Web.HttpContext.Current.Server.MapPath("~/" + ConfigurationManager.AppSettings["ServerPoolsFile"]); string someId = ConfigurationManager.AppSettings["SomeId"]; var requestBody = body; var t2 = Task.Run(() => { var someDump = Helper.MakeRequest(requestBody, Helper.GetUrl(2, someId), 2); JObject wfOutput = JObject.Parse(someDump.WFOutput); var jsonData = wfOutput["output-parameters"]; var poolsList = jsonData[0]["value"]["string"]["value"]; JObject siteJson = JObject.Parse(poolsList.ToString()); string finalFilePath = $"{baseFilePath}_{siteJson["site"]}.json"; if (!System.IO.File.Exists(finalFilePath)) { using (StreamWriter sw = System.IO.File.CreateText(finalFilePath)) { sw.WriteLine(poolsList.ToString()); } } else { System.IO.File.WriteAllText(finalFilePath, poolsList.ToString()); } }).ContinueWith(t => { if (t.IsFaulted) { Console.WriteLine($"t2执行出错:{t.Exception}"); return; } Console.WriteLine("t2 done."); });
内容的提问来源于stack exchange,提问作者Delgado
相关产品推荐
相关产品推荐

