gpt4 book ai didi

c# - 这种 GC.SuppressFinalize() 的使用感觉不对

转载 作者:太空狗 更新时间:2023-10-29 17:35:01 27 4
gpt4 key购买 nike

我在使用供应商库时遇到了一些问题,有时库计算出的实体应该始终包含有效数据时为空。

功能代码(与供应商调试问题后)大致如下:

    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) 并且当应用程序从发布版本运行时,输出参数 validationResultsUsingRecomputedExtrinsics 将为空。如果我从调试版本运行应用程序(附加或不附加调试器),则 validationResultsUsingRecomputedExtrinsics 将包含有效数据。

我不完全理解 GC.SuppressFinalize() 在这种情况下做了什么,或者它是如何解决问题的。我能找到的关于 GC.SuppressFinalize() 的所有信息都是在实现 IDisposable 时使用的。我在“标准”代码中找不到它的任何用途。

添加对 GC.SuppressFinalize(calibrationValidator) 的调用如何/为何解决此问题?

我知道如果不深入了解供应商库的内部结构,可能无法确定,但任何见解都会有所帮助。

该应用程序使用 VS2012 编译,面向 .NET 4.0。该供应商库要求在 app.config 中指定 useLegacyV2RuntimeActivationPolicy="true"选项。

这是我从供应商那里收到的理由:

The SuppressFinalize command makes sure that the garbage collector will not clean something up “early”. It seems like for some reason your application was sometimes having the garbage collector get a bit zealous and clean up the object before you were truly done with it; it is almost certainly scope related and possibly due to the multi-threading causing confusion on the scope of the calibrationValidator. Below is the response I got from Engineering.

Because the variable was created in the local scope, and that function runs in the background thread, Garbage Collection runs in the main thread, and it seems that the Garbage collection is not smart enough in handling multi-thread situations. Sometimes, it just releases it too early (internal execution of validator not finished yet, and still needs this variable).

最佳答案

这很可能是解决过早垃圾收集问题的黑客攻击。非托管代码并不少见,在相机应用程序中很典型。这不是一个健康的 hack,很有可能因为终结器不执行而导致资源泄漏。非托管代码的包装器几乎总是在终结器中做一些事情,它们需要释放非托管内存是很常见的。

问题在于,当非托管代码运行时,calibrationValidator 对象可能会被垃圾回收。在你的程序中有另一个线程使这成为可能,因为另一个线程可以分配对象并触发 GC。代码的所有者在测试时很容易错过这一点,要么是在使用多线程时从未测试过代码,要么只是运气不够好在错误的时间触发了 GC。

您这边的正确解决方法是确保抖动标记在调用之后使用的对象,这样垃圾收集器就不会收集它。您可以通过添加 GC.KeepAlive(calibrationValidator) 来实现在 Execute() 调用之后。

关于c# - 这种 GC.SuppressFinalize() 的使用感觉不对,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15561025/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com