NI TestStand

cancel
Showing results for 
Search instead for 
Did you mean: 

Release a SequenceFile in C#


I am creating a TestStand sequence file and sequences in C#.
After I released the sequence file and shut down the engine I get a warning:
'References to PropertyObjects were not released properly.' The complete warning is attached at the end of the message.

My code is about this:

MyEngine = new EngineClass();
MyEngine.LoadTypePaletteFilesEx(TypeConflictHandlerTypes.ConflictHandler_Error, 0);
SequenceFile TS_SequenceLib MyEngine.GetSequenceFileEx(libfilepath, 0, TypeConflictHandlerTypes.ConflictHandler_Error);
//create a new sequence file
SequenceFile seqFile = MyEngine.NewSequenceFile();
//create and insert some sequences and save the sequence file
seqFile.Save(path);

After finshed inserting the sequences I release both sequence files
seqFile.UnloadModules();
MyEngine.ReleaseSequenceFileEx(seqFile);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(seqFile);
seqFile = null;

I do the same with the other sequencefile TS_SequenceLib and shut down the engine:
MyEngine.UnloadTypePaletteFiles();
MyEngine.UnloadAllModules();
MyEngine.ShutDown(true);               
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(MyEngine);
MyEngine = null;

I tried to iterate through the sequences of each sequence file and remove and release each sequence but it didn't help.

How shoud I release the sequence files, the sequences and the other objects properly to get rid of the warning?


Here is the entire warning:
References to PropertyObjects were not released properly.
    Total number of objects: 44310
    Number of top-level objects: 248

    Note: Some top-level objects may be included if they are referenced by
    an incorrectly released top-level object. For example, an unreleased
    SequenceContext object references a SequenceFile object.

    The following top-level objects were not released:

        Sequences [62 object(s) not released]
            Sequence #1:
                Name: XXXXX_Output_Sensory

            Sequence #2:
                Name: MainSequence

            Sequence #3:
                Name: XXXXX_Output_Diagnostic

            Sequence #4:
                Name: MainSequence

            Sequence #5:
                Name: XXXXX_Output_Optic

            Sequence #6:
                Name: MainSequence

            Sequence #7:
                Name: XXXXX_Output_Acoustic

            Sequence #8:
                Name: MainSequence

            Sequence #9:
                Name: XXXXX_Copy_of_Output_CAN_missing_message

            Sequence #10:
                Name: MainSequence

            Sequence #11:
                Name: XXXXX_Output_CAN_complete

            Sequence #12:
                Name: MainSequence

            Sequence #13:
                Name: XXXXX_Input_Sensory

            Sequence #14:
                Name: MainSequence

            Sequence #15:
                Name: XXXXX_Input_Diagnostic

            Sequence #16:
                Name: MainSequence

            Sequence #17:
                Name: XXXXX_Input_Haptic_external

            Sequence #18:
                Name: MainSequence

            Sequence #19:
                Name: XXXXX_Input_Acoustic

            Sequence #20:
                Name: MainSequence

            Sequence #21:
                Name: XXXXX_Input_CAN_missing_message

            Sequence #22:
                Name: MainSequence

            Sequence #23:
                Name: XXXXX_Input_CAN_complete

            Sequence #24:
                Name: MainSequence

            Sequence #25:
                Name: XXXXX_Input_CCC

            Sequence #26:
                Name: MainSequence

            Sequence #27:
                Name: XXXXX_FlowControl_Ramp_IncrementByTime

            Sequence #28:
                Name: MainSequence

            Sequence #29:
                Name: XXXXX_FlowControl_Ramp_IncrementBy1

            Sequence #30:
                Name: MainSequence

            Sequence #31:
                Name: XXXXX_FlowControl_Loop_TimeControlled

            Sequence #32:
                Name: MainSequence

            Sequence #33:
                Name: XXXXX_FlowControl_Loop_Cycles

            Sequence #34:
                Name: MainSequence

            Sequence #35:
                Name: Par0_thread3

            Sequence #36:
                Name: Par0_thread2

            Sequence #37:
                Name: Par0_thread1

            Sequence #38:
                Name: Par0_thread0

            Sequence #39:
                Name: XXXXX_FlowControl_Parallel

            Sequence #40:
                Name: MainSequence

            Sequence #41:
                Name: XXXXX_FlowControl_TimeRequirement_WaitAtleast

            Sequence #42:
                Name: MainSequence

            Sequence #43:
                Name: XXXXX_FlowControl_TimeRequirement_WaitExactly

            Sequence #44:
                Name: MainSequence

            Sequence #45:
                Name: XXXXX_FlowControl_TimeRequirement_Within

            Sequence #46:
                Name: MainSequence

            Sequence #47:
                Name: MainSequence

            Sequence #48:
                Name: Flow_Wait

            Sequence #49:
                Name: Act_HapticIn

            Sequence #50:
                Name: Act_ReactionOut

            Sequence #51:
                Name: Act_SensoryOut

            Sequence #52:
                Name: Act_DiagnosticOut

            Sequence #53:
                Name: Act_OpticOut

            Sequence #54:
                Name: Act_AcousticOut

            Sequence #55:
                Name: Act_SensoryIn

            Sequence #56:
                Name: Act_DiagnosticIn

            Sequence #57:
                Name: Act_AcousticIn

            Sequence #58:
                Name: Act_CCCIn

            Sequence #59:
                Name: Act_CANOut

            Sequence #60:
                Name: Flow_Parallel

            Sequence #61:
                Name: Act_CANIn

            Sequence #62:
                Name: MainSequence


        Type Definitions [44 object(s) not released]
            Type Definition #1:
                Name: OpenModelManager

            Type Definition #2:
                Name: AdditionalResults

            Type Definition #3:
                Name: Goto

            Type Definition #4:
                Name: Label

            Type Definition #5:
                Name: Statement

            Type Definition #6:
                Name: SequenceCall

            Type Definition #7:
                Name: NI_Wait

            Type Definition #8:
                Name: NI_Flow_End

 ...
        Note: More objects were not released, but not listed.

0 Kudos
Message 1 of 6
(5,393 Views)

It looks like the message is specifically about sequences rather than sequence files. Could you post a snippet of the code where you're adding new sequences to the sequence file? It's possible that a reference in that section of the code needs to be closed in order to resolve the error message.

0 Kudos
Message 2 of 6
(5,389 Views)

A couple issues:

 

1) You are calling GetSequenceFileEx() and storing the reference in TS_SequenceLib, but you are never calling ReleaseSequenceFileEx() on it and are never calling Marshal.FinalReleaseComObject() on it.

 

2) Rather than calling:

Marshal.FinalReleaseComObject()

 

Before exiting, just set all references other than the engine to null (or write your code such that those references are no longer in scope). Then, before the engine reference goes out of scope, do the following:

 

GC.Collect();

GC.WaitForPendingFinalizers();

GC.Collect();

GC.WaitForPendingFinalizers();

// You have to do the GC.Collect() and GC.WaitForPendingFinalizers() calls twice to ensure all objects pending for garbage collection are destroyed due to how .NET does garbage collection.

 

Or call the function DoSynchronousGCForCOMObjectDestruction() in the <TestStand>\API\DotNet\Assemblies\CurrentVersion\NationalInstruments.TestStand.Utility.dll assembly.

 

This will ensure that the engine is deleted last and thus its leak detection code won't report any leaks due to objects being held onto for garbage collection.

 

Trying to call Marshal.FinalReleaseComObject or Marshal.ReleaseComObject() on every reference is a lot more trouble and not really necessary if you just force garabage collection before the engine is destroyed.

 

There are other places you might want to force garbage collection, such as when a sequence file or execution is closed to ensure a more timely execution of Unload callbacks, but if you aren't using any unload callbacks or you are disabling them then this isn't necessary.

 

Hope this helps,

-Doug

Message 3 of 6
(5,386 Views)

Hi Doug,

 

thanks for pointing out !

 

Juergen

--Signature--
Sessions NI-Week 2017 2016
Feedback or kudos are welcome
0 Kudos
Message 4 of 6
(5,362 Views)


Hi,

thank you for the quick answers!

1) I am calling GetSequenceFileEx() and Marshal.FinalReleaseComObject() for TS_SequenceLib. I only mentioned,
that I release both sequence files but I don't inserted the code snippet twice.

2) I tried to call GC.Collect() and GC.WaitForPendingFinalizers(); and I also tried DoSynchronousGCForCOMObjectDestruction()
but it didn't help.

I have attached the code snippet in which I create the sequences. This happens in separate function, so I thought,
the references to the sequences are out of scope after returning back to the main function but it seems that they are still existing.
How should I release the sequences?
I have tried FinalReleaseComObject(seq) and seqFile.RemoveSequence(i).

Should I close the sequence file, if yes how?

Thank you for the help.


The code snippet how I create the sequences:
//create the sequence
seq = MyEngine.NewSequence();
seq.Name = tcName;

//create a step
step = Create_newStep("SequenceCall", "OpticOut", child.GetAttribute("Target") + comment);    //child is an XmlElement
SequenceCallModule mod = (SequenceCallModule)step.Module;
//set some mod.Parameters
//identify index of the step

//insert the step to the sequence
seq.InsertStep(step, index, StepGroups.StepGroup_Main);

seqFile.InsertSequenceEx(0, seq);



private Step Create_newStep(string type, string name, string comment)
{
    Step step = MyEngine.NewStep("", type);
    step.Name = name;
    step.AsPropertyObject().Comment = comment;

    NationalInstruments.TestStand.Interop.API.Sequence seq = TS_SequenceLib.GetSequenceByName("Act_CANIn");
    SequenceCallModule objModule = (SequenceCallModule)step.Module;
    objModule.SequenceName = "Act_" + name;
    objModule.UseSequenceParameterPrototype = false;
    //objModule.LoadParametersFromSequence(seq);
    objModule.SequenceFilePath = "MM_SpecEdit_Lib.seq";
    objModule.LoadPrototypeFromSequence(seq, 0);
    objModule.UseSequenceParameterPrototype = true;
    
    return step;
}


0 Kudos
Message 5 of 6
(5,350 Views)
Are you calling engine.ReleaseSequenceFileEx on the file after you are done with it?

You do not need to use the marshal functions. Doing gc collect as I described previously after all references other than the engine have gone out of scope is sufficient. BUT you do need to call ReleaseSequenceFileEx for each file you got by calling GetSequenceFileEx. Make sure you are doing that.

-Doug
0 Kudos
Message 6 of 6
(5,344 Views)