我在使用供应商库时遇到了一些问题,有时由库计算的实体在它应该始终包含有效数据时会为空。
功能代码(与供应商调试问题后)大致如下:
Task.Factory.StartNew(() => ValidateCalibration(pelRectRaw2Ds, crspFeatures, Calibration.Raw2DFromPhys3Ds));
.....
private void ValidateCalibration(List<Rectangle> pelRectRaw2Ds, List<List<3DCrspFeaturesCollection>> crspFeatures, List<3DCameraCalibration> getRaw2DFromPhys3Ds)
{
var calibrationValidator = new 3DCameraCalibrationValidator();
// This is required according to vendor otherwise validationResultsUsingRecomputedExtrinsics is occasionally null after preforming the validation
GC.SuppressFinalize(calibrationValidator);
3DCameraCalibrationValidationResult validationResultUsingOriginalCalibrations;
3DCameraCalibrationValidationResult validationResultsUsingRecomputedExtrinsics;
calibrationValidator.Execute(pelRectRaw2Ds, crspFeatures, getRaw2DFromPhys3Ds, out validationResultUsingOriginalCalibrations, out validationResultsUsingRecomputedExtrinsics);
Calibration.CalibrationValidations.Add(new CalibrationValidation
{
Timestamp = DateTime.Now,
UserName = Globals.InspectionSystemObject.CurrentUserName,
ValidationResultUsingOriginalCalibrations = validationResultUsingOriginalCalibrations,
ValidationResultsUsingRecomputedExtrinsics = validationResultsUsingRecomputedExtrinsics
});
}
验证过程是一个相当耗时的操作,所以我将它交给一个任务。我遇到的问题是,最初我没有调用 GC.SuppressFinalize(calibrationValidator) 并且当应用程序从 Release 版本运行时,输出参数 validationResultsUsingRecomputedExtrinsics 将为空。如果我从 Debug 版本运行应用程序(无论是否附加了 Debugger),那么 validationResultsUsingRecomputedExtrinsics 将包含有效数据。
我不完全理解 GC.SuppressFinalize() 在这种情况下做了什么,或者它是如何解决问题的。我能找到的关于 GC.SuppressFinalize() 的一切都是在实现 IDisposable 时使用的。我在“标准”代码中找不到它的任何用途。
添加对 GC.SuppressFinalize(calibrationValidator) 的调用如何/为什么解决此问题?
我知道,如果没有对供应商库内部的深入了解,可能无法确定,但任何洞察力都会有所帮助。
该应用程序使用 VS2012 编译,面向 .NET 4.0。该供应商库要求在 app.config 中指定 useLegacyV2RuntimeActivationPolicy="true" 选项。
这是我从供应商那里收到的理由:
SuppressFinalize 命令确保垃圾收集器不会“提前”清理某些东西。似乎由于某种原因,您的应用程序有时让垃圾收集器有点热心并在您真正完成对象之前清理它;几乎可以肯定它与范围相关,并且可能是由于多线程导致了calibrationValidator 范围的混淆。以下是我从工程部得到的回复。
因为变量是在本地范围内创建的,而该函数在后台线程中运行,所以垃圾收集运行在主线程中,看起来垃圾收集在处理多线程情况时不够聪明。有时,它只是过早地释放它(验证器的内部执行尚未完成,仍然需要这个变量)。