首页 文章

查询并行foreach结果会导致Null引用错误

提问于
浏览
1

我有一个类似下面的平行foreach语句

Parallel.ForEach(spacialRecords, (spacerecord) =>
                   {
                       List<MeterValue> dat = new List<MeterValue>();
                       var latitude = Geometry.Y;
                       var longitude = spacerecord.Geometry.X;
                       var timeStamp = spacerecord.Timestamp;

                       foreach (var wdItem in workingData)
                       {
                           RepresentationValue spaceMeteredValue = spacerecord.GetMeterValue(wdItem);
                           if (spaceMeteredValue != null && wdItem.Representation != null)
                           {
                               var objMeterValue = new MeterValue();
                               objMeterValue.key = wdItem.Representation.Code;
                               objMeterValue.value = spaceMeteredValue.Designator != null ? Convert.ToString(spaceMeteredValue.Designator) : "";
                               dat.Add(objMeterValue);
                           }
                       }

                       listSpacialRecords.Add(new
                       {

                           operationLogDataId = yieldMaster.OperationalLogDataModelResponse.Id,
                           order = deviceElement.Order,
                           totalDistanceTravelled = deviceElement.TotalDistanceTravelled,
                           totalElapsedTime = deviceElement.TotalElapsedTime,
                           uploadedOn = DateTime.Now.ToUniversalTime(),
                           collectedOn = timeStamp.ToUniversalTime(),
                           cropId = "8296e610-c055-11e7-851e-ad7650a5f99c",
                           productId = productid,
                           latitude = latitude,
                           longitude = longitude,
                           deviceConfigurationId = deviceElement.DeviceConfigurationId,
                           operationDataId = deviceElement.OperationDataId,
                           spatialRecords = dat,
                           depth = depth,
                           timeStamp = timeStamp,
                           totaldata = totalRecordCount

                       });

                   });

listSpacialRecords是一个动态类型列表,我在listSpacialRecords中获得了大量数据 . 所以我在这里做一些过滤,因为我已经添加了下面的代码

listSpacialRecords = listSpacialRecords
                  .Skip(1)
                  .Aggregate(
                      listSpacialRecords.Take(1).ToList(),
                      (a, x) =>
                      {
                          if (x.timeStamp.Subtract(a.Last().timeStamp).TotalSeconds >= 10.0)
                          {
                              a.Add(x);
                          }
                          return a;
                      });

代码不在foreach循环中 . 当我执行此操作时,我得到的错误就像

Cannot perform run time binding on a null reference

但是当我删除并行并使用正常的foreach循环时,代码工作正常 .

注意:我做了一个断点,我发现listSpacialRecords正确地显示了所有记录,我已经用quickwatch检查了最后一个元素数据是否可用但仍然失败

任何人都可以帮我弄清楚我的问题是什么吗?

1 回答

  • 3
    listSpacialRecords.Add(...);
    

    我默认情况下是'm assuming that this method is not explicitly thread-safe (it won' . 所有的线程都在说同一个 listSpacialRecords .

    你在 Parallel.ForEach 中执行此操作的那一刻,你有一个非常冒险的线程竞争 - 如果两个线程同时调用 .Add ,可能会发生所有数量的坏事 - 包括数据丢失 .

    所以:同步所有对此 Add 的调用 . 这可以简单如下:

    var newValue = new {
        operationLogDataId = yieldMaster.OperationalLogDataModelResponse.Id,
        // etc etc...
    };                           .
    lock(listSpacialRecords) {
        listSpacialRecords.Add(newValue);
    }
    

    还有 dat.Add ,但是这个 dat 是每个调用的上下文绑定,因此不需要同步 .

相关问题