Run Perfmon.exe and add these counters:
- Process / Private bytes
- .NET CLR Memory / # bytes in all heaps
- .NET CLR LocksAndThreads / # of current logical threads
Run your application for a representative length of time and exercise its functionality.
If Private bytes is increasing but # bytes in all heaps is not, then unmanaged memory is leaking.
If both both are increasing, then managed memory is leaking.
If the # of current logical threads is increasing beyond what you expect, then thread stacks are leaking.
If Private Bytes is periodically jumping in 1MB increments with a corresponding increase in # of current logical Threads, a thread stack leak is the likely cause.