ライブラリによって計算されたエンティティが常に有効なデータを持っているはずなのに、時折nullになるベンダーライブラリの利用に関していくつかの問題がありました。
機能しているコード (ベンダーとの問題をデバッグした後) は、おおよそ次のとおりです。
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 が null になることでした。アプリケーションをデバッグ ビルドから実行した場合 (デバッガーが接続されているかどうかに関係なく)、validationResultsUsingRecomputedExtrinsics には有効なデータが含まれます。
この状況で GC.SuppressFinalize() が何をしたか、または問題をどのように修正したかを完全には理解していません。GC.SuppressFinalize() に関して私が見つけることができるのは、IDisposable を実装するときに使用されることだけです。「標準」コードでの使用は見つかりません。
GC.SuppressFinalize(calibrationValidator) への呼び出しを追加すると、この問題がどのように/なぜ修正されるのですか?
ベンダー ライブラリの内部構造に関する詳細な知識がなければ、確実に知ることはできないかもしれないことは理解していますが、洞察は役に立ちます。
アプリケーションは VS2012 でコンパイルされ、.NET 4.0 を対象としています。そのベンダー ライブラリでは、app.config で useLegacyV2RuntimeActivationPolicy="true" オプションが指定されている必要があります。
これは、ベンダーから受け取った正当な理由です。
SuppressFinalize コマンドは、ガベージ コレクターが何かを「早期」にクリーンアップしないようにします。なんらかの理由で、アプリケーションがガベージコレクターに少し熱心になり、オブジェクトを完全に処理する前にオブジェクトをクリーンアップすることがあったようです。これはほぼ確実にスコープに関連しており、おそらくマルチスレッドが原因で、calibrationValidator のスコープに混乱が生じています。以下は、エンジニアリングから得た回答です。
変数はローカル スコープで作成され、その関数はバックグラウンド スレッドで実行されるため、ガベージ コレクションはメイン スレッドで実行され、ガベージ コレクションはマルチスレッドの状況を処理するのに十分スマートではないようです。場合によっては、リリースが早すぎることがあります (バリデーターの内部実行がまだ終了していないため、この変数が必要です)。