У меня были некоторые проблемы с использованием библиотеки поставщика, где иногда объект, вычисленный библиотекой, был бы нулевым, хотя в нем всегда должны быть действительные данные.
Функциональный код (после отладки проблемы с поставщиком) примерно следующий:
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 был бы нулевым. Если бы я запустил приложение из отладочной сборки (с прикрепленным отладчиком или без него), тогда validationResultsUsingRecomputedExtrinsics будет содержать действительные данные.
Я не совсем понимаю, что GC.SuppressFinalize () сделал в этой ситуации или как он устранил проблему. Все, что я могу найти относительно GC.SuppressFinalize (), - это то, что он используется при реализации IDisposable. Я не могу найти ему никакого применения в "стандартном" коде.
Как / почему добавление вызова к GC.SuppressFinalize (CalibrationValidator) решает эту проблему?
Я понимаю, что без глубоких знаний о внутреннем устройстве библиотеки поставщика, возможно, будет невозможно узнать наверняка, но любое понимание может помочь.
Приложение скомпилировано с помощью VS2012, ориентированного на .NET 4.0. Эта библиотека поставщика требует, чтобы параметр useLegacyV2RuntimeActivationPolicy = "true" был указан в app.config.
Это обоснование, которое я получил от продавца:
Команда SuppressFinalize гарантирует, что сборщик мусора не очистит что-то «раньше». Похоже, что по какой-то причине ваше приложение иногда заставляло сборщика мусора немного усердствовать и очищать объект до того, как вы действительно закончили с ним; это почти наверняка связано с областью видимости и, возможно, из-за многопоточности, вызывающей путаницу в области калибровки Validator. Ниже я получил ответ от инженерного отдела.
Поскольку переменная была создана в локальной области, а эта функция выполняется в фоновом потоке, сборка мусора выполняется в основном потоке, и кажется, что сборка мусора недостаточно умна для обработки многопоточных ситуаций. Иногда он просто освобождает его слишком рано (внутреннее выполнение валидатора еще не завершено, и эта переменная все еще нуждается в этой переменной).
3DCameraCalibrationValidator
(потому что авторы не ожидали, что финализатор может работать во время выполненияExecute()
). ИспользованиеSuppressFinalize()
позволяет обойти эту ошибку. - person svick   schedule 22.03.2013