tinklerj

Thread Leak from ASP.Net Web Service calling PI-SDK

Discussion created by tinklerj on Oct 30, 2012
Latest reply on Nov 16, 2012 by charlie@osisoft.com

Further to a  http://vcampus.osisoft.com/discussion_hall/development_with_osisoft_sdks/f/8/t/3192.aspx about PI-SDK, threading and ASP.Net:

I have an application running in an ASP.Net Web service and using PI-SDK to read data.  To slim down a lot of code into the essentials:

- The Web service and its worker threads run in STA apartments (not that this seems to make any difference).

On first time initialization:

1. a thread is run to create a ServerManager object.  This thread creates the first PISDK object but does not terminate (sleeps 10 sec at low priority and loops) as recommended in the SDK help, or at least the way I understood it.

Code in the SDK accessing class:

 

private static ServerManager SDKServerMan;
private static PISDK.PISDK mySDK;
//...
// in the thread
SDKServerMan = new PISDK.ServerManager();
mySDK = SDKServerMan.PISDK;

 
2. a PointList object is then created (from a worker thread) for an array of tag names (\\server\tag).  This code is called once only.  Note: all tags are on the same server.

private PointList tags;
//...
string[] tagNames = new string[numoftags];
//...
tags = new PISDK.PointListClass();
IPointList2 ipl = (IPointList2)tags;
PIErrors tagErrors = ipl.AddItems((object)tagNames);
//... check errors ...
System.Runtime.InteropServices.Marshal.ReleaseComObject(tagErrors); 

 
Each time the service method is called (atTime is a method argument) it essentially does this:

//...
NamedValues nvErrors;
PointValues dataRead = tags.Data.ArcValue(atTime, RetrievalTypeConstants.rtAuto, out nvErrors);
//... check nvErrors ...
System.Runtime.InteropServices.Marshal.ReleaseComObject(nvErrors); 

// process tag values read
for (int tagn = 0; tagn < dataRead.Count; tagn++)
{
     PointValue pv = dataRead[tagn + 1];
     PIPoint pipt = pv.PIPoint;
     PIValue val = pv.PIValue;
     ....
     System.Runtime.InteropServices.Marshal.ReleaseComObject(val);
     System.Runtime.InteropServices.Marshal.ReleaseComObject(pipt);
     System.Runtime.InteropServices.Marshal.ReleaseComObject(pv);
}
System.Runtime.InteropServices.Marshal.ReleaseComObject(dataRead);
//...

 

The problem is, I am finding that the ASP.Net worker process is leaking threads (and their associated stack at 1MB a pop).  See picture.  Debugging with Visual Studio 2010, the list of managed threads does not seem to increase, so I can only assume they are unmanaged background threads created by PI-SDK.  But why are these threads getting stuck?  The example uses 5 tags but the number seems to be irrelevant.

I'm assuming that all PISDK objects created will be in the hierarchy pointed at by mySDK (since no other code creates PISDK objects).

I would love to use AF SDK's Rich Data Model and leave all this COM nonsense behind.  Unfortunately I haven't time and I can't use a beta SDK in a production environment.  Anyway I won't be able to use that until it supports data fanout to a collective.

Outcomes