.NET Core 3.1异步Task中DateTime.UtcNow报NullReferenceException求助
.NET Core 3.1异步调试中DateTime.UtcNow空引用异常的解决办法
问题描述
调试.NET Core 3.1服务时,执行代码DateTime maxOwnerValidDate = DateTime.UtcNow;会抛出空引用异常:
System.NullReferenceException: 'Object reference not set to an instance of an object.' maxOwnerValidDate._dateData was null.
已知_dateData是.NET 6/7新增的内部属性,本地开发环境已升级至.NET 6,该异常仅在异步Task中手动移动调试指针时触发,非异步环境或正常逐行调试无问题。目前不想升级项目,也不愿回滚.NET 6环境,需找到可行解决办法。
可复现该问题的代码如下:
public async Task ProcessWorkflow(List<Object> steps) { foreach (Object step in steps) { bool pushingForward = true; //<<< 断点1 <<< DateTime maxOwnerValidDate = DateTime.UtcNow; //手动跳至此处后按F10 bool success = await ProcessWorkflowSteps(step); //无异常 } } public async Task<bool> ProcessWorkflowSteps(Object step) { List<int> someStuff = new List<int>() { 1, 2, 4, 5 }; bool thisShouldRun = false; if (thisShouldRun) //<<< 断点2 <<< { //手动跳至if块内按F10 DateTime maxOwnerValidDate = DateTime.UtcNow; //按F10触发异常 //若移除下一行则无异常 List<int> Ids = someStuff.Where(stuff => maxOwnerValidDate <= DateTime.UtcNow).ToList(); await Task.Delay(1000); } return true; }
原因分析
这是跨.NET版本调试的兼容性问题:
- .NET 6对
DateTime结构做了内部实现改动,新增_dateData字段,但.NET Core 3.1的DateTime并无该字段。 - 用.NET 6的调试器调试.NET Core 3.1项目时,手动移动调试指针(跳步)会破坏调试器对
DateTime实例的初始化逻辑,导致未在.NET Core 3.1中存在的_dateData字段被标记为null,后续代码引用该实例时触发异常。
解决方案
以下是无需升级项目或回滚.NET 6环境的解决办法:
- 避免手动跳步调试:调试异步代码时,不要手动移动调试指针到未执行的代码行,按正常流程用F10/F11逐行调试即可规避异常。
- 显式构造DateTime实例:替换原赋值语句,通过Ticks直接构造实例,绕开调试器的异常逻辑:
// 替代 DateTime maxOwnerValidDate = DateTime.UtcNow; DateTime maxOwnerValidDate = new DateTime(DateTime.UtcNow.Ticks, DateTimeKind.Utc); - 调整调试器设置:在Visual Studio中修改调试选项:
- 打开项目属性→调试→常规,取消勾选「启用“仅我的代码”」
- 打开项目属性→生成,取消勾选「优化代码」
- 提取临时变量:将
DateTime.UtcNow的结果先存入临时变量,再用于后续逻辑,减少调试器对实例初始化的干扰:var utcNow = DateTime.UtcNow; DateTime maxOwnerValidDate = utcNow; List<int> Ids = someStuff.Where(stuff => maxOwnerValidDate <= utcNow).ToList();
内容的提问来源于stack exchange,提问作者Jessel Aquing
相关产品推荐
相关产品推荐

